Commit ac0f4478 authored by Marja Hölttä's avatar Marja Hölttä Committed by V8 LUCI CQ

[web snapshots] Support concatenating snapshots

After the snapshot data ends, interpret the rest as normal JS code.

Bug: v8:11525
Change-Id: I8de4cf4027e582e6b8e330dda7708623373d2675
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3263896Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77741}
parent 0e546f54
......@@ -834,9 +834,36 @@ bool WebSnapshotDeserializer::Deserialize() {
ProcessDeferredReferences();
DeserializeExports();
DCHECK_EQ(deferred_references_->Length(), 0);
if (deserializer_->position_ != deserializer_->end_) {
Throw("Web snapshot: Snapshot length mismatch");
return false;
// If there is more data, treat it as normal JavaScript.
DCHECK_LE(deserializer_->position_, deserializer_->end_);
auto remaining_bytes = deserializer_->end_ - deserializer_->position_;
if (remaining_bytes > 0 && remaining_bytes < v8::String::kMaxLength) {
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
v8::Local<v8::String> source =
v8::String::NewFromUtf8(
v8_isolate, reinterpret_cast<const char*>(deserializer_->position_),
NewStringType::kNormal, static_cast<int>(remaining_bytes))
.ToLocalChecked();
ScriptOrigin origin(v8_isolate, v8::String::NewFromUtf8Literal(
v8_isolate, "(web snapshot)",
NewStringType::kInternalized));
ScriptCompiler::Source script_source(source, origin);
Local<UnboundScript> script;
if (!ScriptCompiler::CompileUnboundScript(v8_isolate, &script_source)
.ToLocal(&script)) {
DCHECK(isolate_->has_pending_exception());
return false;
}
Local<Value> result;
if (!script->BindToCurrentContext()
->Run(v8_isolate->GetCurrentContext())
.ToLocal(&result)) {
DCHECK(isolate_->has_pending_exception());
return false;
}
}
if (FLAG_trace_web_snapshot) {
......
......@@ -700,5 +700,53 @@ TEST(FunctionKinds) {
kObjectCount);
}
// Test that concatenating JS code to the snapshot works.
TEST(Concatenation) {
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
const char* snapshot_source = "var foo = {a: 1};\n";
const char* source_to_append = "var bar = {a: 10};";
const char* test_source = "foo.a + bar.a";
uint32_t kObjectCount = 1;
WebSnapshotData snapshot_data;
{
v8::HandleScope scope(isolate);
v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context);
CompileRun(snapshot_source);
v8::Local<v8::PrimitiveArray> exports = v8::PrimitiveArray::New(isolate, 1);
v8::Local<v8::String> str =
v8::String::NewFromUtf8(isolate, "foo").ToLocalChecked();
exports->Set(isolate, 0, str);
WebSnapshotSerializer serializer(isolate);
CHECK(serializer.TakeSnapshot(new_context, exports, snapshot_data));
CHECK(!serializer.has_error());
CHECK_NOT_NULL(snapshot_data.buffer);
CHECK_EQ(kObjectCount, serializer.object_count());
}
auto buffer_size = snapshot_data.buffer_size + strlen(source_to_append);
std::unique_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
memcpy(buffer.get(), snapshot_data.buffer, snapshot_data.buffer_size);
memcpy(buffer.get() + snapshot_data.buffer_size, source_to_append,
strlen(source_to_append));
{
v8::HandleScope scope(isolate);
v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate);
CHECK(deserializer.UseWebSnapshot(buffer.get(), buffer_size));
CHECK(!deserializer.has_error());
CHECK_EQ(kObjectCount, deserializer.object_count());
v8::Local<v8::Number> result = CompileRun(test_source).As<v8::Number>();
CHECK_EQ(11, result->Value());
}
}
} // namespace internal
} // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment