Skip to content

Commit 6879ceb

Browse files
authored
Add client bootstrapper (#124)
* client: Add bootstrapper * client: Use std::vector instead of raw C array * client: Remove some redundant code Former-commit-id: d49af4d
1 parent 566f9e8 commit 6879ceb

6 files changed

+39
-28
lines changed

client/.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ tools/extra.bat
1313
deps/v8/include/
1414
deps/v8/lib/
1515
deps/v8/update.json
16+
17+
# Generated
18+
19+
src/bootstrap.js.gen

client/CMakeLists.txt

+9
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ endmacro()
4141
GroupSources(${PROJECT_SOURCE_DIR}/src "Source Files")
4242
GroupSources("../shared" "Shared Files")
4343

44+
function(make_includable input_file output_file)
45+
file(READ ${input_file} content)
46+
set(delim "for_c++_include")
47+
set(content "R\"${delim}(\n${content})${delim}\"")
48+
file(WRITE ${output_file} "${content}")
49+
endfunction(make_includable)
50+
51+
make_includable("src/bootstrap.js" "src/bootstrap.js.gen")
52+
4453
include_directories(
4554
${ALTV_JS_CPP_SDK}
4655
${ALTV_JS_DEPS_DIR}/v8/include

client/src/CV8Resource.cpp

+15-26
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ void CV8ResourceImpl::ProcessDynamicImports()
5656
dynamicImports.clear();
5757
}
5858

59+
static std::string bootstrap_code =
60+
#include "bootstrap.js.gen"
61+
;
62+
5963
extern V8Module altModule;
6064
bool CV8ResourceImpl::Start()
6165
{
@@ -94,34 +98,24 @@ bool CV8ResourceImpl::Start()
9498
alt::IPackage::File* file = pkg->OpenFile(path);
9599

96100
size_t fileSize = pkg->GetFileSize(file);
97-
uint8_t* byteBuffer = new uint8_t[fileSize];
98-
pkg->ReadFile(file, byteBuffer, fileSize);
101+
std::vector<uint8_t> byteBuffer(fileSize);
102+
pkg->ReadFile(file, byteBuffer.data(), fileSize);
99103
pkg->CloseFile(file);
100104

101-
isUsingBytecode = IsBytecodeModule(byteBuffer, fileSize);
105+
isUsingBytecode = IsBytecodeModule(byteBuffer.data(), fileSize);
102106

103107
Log::Info << "[V8] Starting script " << path << Log::Endl;
104108

105109
bool result = V8Helpers::TryCatch([&]() {
106110
v8::MaybeLocal<v8::Module> maybeModule;
107-
if(!isUsingBytecode)
108-
{
109-
alt::String src{ (char*)byteBuffer, fileSize };
110-
v8::ScriptOrigin scriptOrigin(isolate, V8Helpers::JSValue(path), 0, 0, false, -1, v8::Local<v8::Value>(), false, false, true, v8::Local<v8::PrimitiveArray>());
111-
v8::ScriptCompiler::Source source{ V8Helpers::JSValue(src), scriptOrigin };
112-
maybeModule = v8::ScriptCompiler::CompileModule(isolate, &source);
113-
}
114-
else
115-
{
116-
maybeModule = ResolveBytecode(path, byteBuffer, fileSize);
117-
}
111+
v8::ScriptOrigin scriptOrigin(isolate, V8Helpers::JSValue("<bootstrapper>"), 0, 0, false, -1, v8::Local<v8::Value>(), false, false, true, v8::Local<v8::PrimitiveArray>());
112+
v8::ScriptCompiler::Source source{ V8Helpers::JSValue(bootstrap_code), scriptOrigin };
113+
maybeModule = v8::ScriptCompiler::CompileModule(isolate, &source);
118114

119115
if(maybeModule.IsEmpty()) return false;
120116

121117
v8::Local<v8::Module> curModule = maybeModule.ToLocalChecked();
122118

123-
modules.emplace(path, v8::UniquePersistent<v8::Module>{ isolate, curModule });
124-
125119
auto exports = altModule.GetExports(isolate, ctx);
126120
// Overwrite global console object
127121
auto console = ctx->Global()->Get(ctx, V8Helpers::JSValue("console")).ToLocalChecked().As<v8::Object>();
@@ -141,13 +135,16 @@ bool CV8ResourceImpl::Start()
141135
ctx->Global()->Set(ctx, V8Helpers::JSValue("clearTimeout"), exports->Get(ctx, V8Helpers::JSValue("clearTimeout")).ToLocalChecked());
142136

143137
ctx->Global()->Set(ctx, V8Helpers::JSValue("__internal_get_exports"), v8::Function::New(ctx, &StaticRequire).ToLocalChecked());
138+
ctx->Global()->Set(ctx, V8Helpers::JSValue("__internal_main_path"), V8Helpers::JSValue(path));
144139

145140
bool res = curModule->InstantiateModule(ctx, CV8ScriptRuntime::ResolveModule).IsJust();
146141

147142
if(!res) return false;
148143

149144
v8::MaybeLocal<v8::Value> v = curModule->Evaluate(ctx);
150145

146+
isPreloading = false;
147+
151148
if(v.IsEmpty()) return false;
152149

153150
if(curModule->GetStatus() == v8::Module::Status::kErrored)
@@ -165,17 +162,9 @@ bool CV8ResourceImpl::Start()
165162
alt::MValue _exports = V8Helpers::V8ToMValue(curModule->GetModuleNamespace());
166163
resource->SetExports(_exports.As<alt::IMValueDict>());
167164

168-
if(curModule->IsGraphAsync()) Log::Warning << "[V8] Top level await is an experimental feature, use it at your own risk" << Log::Endl;
169-
170165
Log::Info << "[V8] Started script " << path << Log::Endl;
171166
return true;
172167
});
173-
delete byteBuffer;
174-
175-
if(!result)
176-
{
177-
modules.erase(path);
178-
}
179168

180169
DispatchStartEvent(!result);
181170

@@ -514,9 +503,9 @@ v8::MaybeLocal<v8::Value> CV8ResourceImpl::GetSyntheticModuleExport(v8::Local<v8
514503
return v8::MaybeLocal<v8::Value>();
515504
}
516505

517-
void CV8ResourceImpl::HandleWebViewEventQueue(const alt::Ref<alt::IWebView> view)
506+
void CV8ResourceImpl::HandleWebViewEventQueue(alt::Ref<alt::IWebView> view)
518507
{
519-
auto& eventQueuesMap = this->GetWebviewsEventQueue();
508+
auto& eventQueuesMap = GetWebviewsEventQueue();
520509
if(!eventQueuesMap.count(view)) return;
521510

522511
auto& eventQueue = eventQueuesMap.at(view);

client/src/CV8Resource.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ class CV8ResourceImpl : public V8ResourceImpl, public IImportHandler
169169
v8::Local<v8::Module> CreateSyntheticModule(const std::string& name, v8::Local<v8::Value> exportValue);
170170
v8::MaybeLocal<v8::Value> GetSyntheticModuleExport(v8::Local<v8::Module> syntheticModule);
171171

172+
bool IsPreloading()
173+
{
174+
return isPreloading;
175+
}
176+
172177
private:
173178
friend class CV8ScriptRuntime;
174179

@@ -185,7 +190,7 @@ class CV8ResourceImpl : public V8ResourceImpl, public IImportHandler
185190
{
186191
return webViewsEventsQueue;
187192
}
188-
void HandleWebViewEventQueue(const alt::Ref<alt::IWebView> view);
193+
void HandleWebViewEventQueue(alt::Ref<alt::IWebView> view);
189194

190195
std::unordered_set<alt::Ref<alt::IBaseObject>> ownedObjects;
191196

@@ -201,4 +206,6 @@ class CV8ResourceImpl : public V8ResourceImpl, public IImportHandler
201206

202207
// Key = Module identity hash, Value = Export value
203208
std::unordered_map<int, V8Helpers::CPersistent<v8::Value>> syntheticModuleExports;
209+
210+
bool isPreloading = true;
204211
};

client/src/CV8ScriptRuntime.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ CV8ScriptRuntime::CV8ScriptRuntime()
132132
});
133133
};
134134

135-
if(Instance().resourcesLoaded && resource->GetResource()->IsStarted())
135+
if(Instance().resourcesLoaded && resource->GetResource()->IsStarted() || resource->IsPreloading())
136136
{
137137
// instantly resolve the module
138138
domodule();

client/src/bootstrap.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// clang-format off
2+
await import(`/${__internal_main_path}`);

0 commit comments

Comments
 (0)