| Index: third_party/WebKit/Source/bindings/core/v8/V8SnapshotCreator.cpp
|
| diff --git a/third_party/WebKit/Source/bindings/core/v8/V8SnapshotCreator.cpp b/third_party/WebKit/Source/bindings/core/v8/V8SnapshotCreator.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8f74186d124f2a90002709d141699a1c52845fb9
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/bindings/core/v8/V8SnapshotCreator.cpp
|
| @@ -0,0 +1,232 @@
|
| +#include "bindings/core/v8/V8SnapshotCreator.h"
|
| +
|
| +#include <cstring>
|
| +
|
| +#include "bindings/core/v8/DOMWrapperWorld.h"
|
| +#include "bindings/core/v8/GeneratedCodeHelper.h"
|
| +#include "bindings/core/v8/V8Document.h"
|
| +#include "bindings/core/v8/V8HTMLDocument.h"
|
| +#include "bindings/core/v8/V8Initializer.h"
|
| +#include "bindings/core/v8/V8Node.h"
|
| +#include "bindings/core/v8/V8ObjectConstructor.h"
|
| +#include "bindings/core/v8/V8PerIsolateData.h"
|
| +#include "bindings/core/v8/V8PrivateProperty.h"
|
| +#include "bindings/core/v8/V8Window.h"
|
| +
|
| +#include <v8.h>
|
| +
|
| +namespace blink {
|
| +
|
| +namespace {
|
| +
|
| +bool g_taking_snapshot = false;
|
| +
|
| +// NOTE(peria): This method is almost a copy of
|
| +// V8PerContext::CreateWrapperFromCacheSlowCase().
|
| +v8::Local<v8::Function> ConstructPlainType(v8::Isolate* isolate,
|
| + const DOMWrapperWorld& world,
|
| + v8::Local<v8::Context> context,
|
| + const WrapperTypeInfo* type) {
|
| + v8::Context::Scope scope(context);
|
| + // We shouldn't reach this point for the types that are implemented in v8 such
|
| + // as typed arrays and hence don't have domTemplateFunction.
|
| + DCHECK(type->dom_template_function);
|
| + v8::Local<v8::FunctionTemplate> interface_template =
|
| + type->domTemplate(isolate, world);
|
| + // Getting the function might fail if we're running out of stack or memory.
|
| + v8::Local<v8::Function> interface_object;
|
| + if (!interface_template->GetFunction(context).ToLocal(&interface_object))
|
| + return v8::Local<v8::Function>();
|
| +
|
| + if (type->parent_class) {
|
| + v8::Local<v8::Object> prototype_template =
|
| + ConstructPlainType(isolate, world, context, type->parent_class);
|
| + CHECK(interface_object->SetPrototype(context, prototype_template)
|
| + .ToChecked());
|
| + }
|
| +
|
| + v8::Local<v8::Value> prototype_value;
|
| + CHECK(interface_object->Get(context, V8AtomicString(isolate, "prototype"))
|
| + .ToLocal(&prototype_value));
|
| + CHECK(prototype_value->IsObject());
|
| + v8::Local<v8::Object> prototype_object = prototype_value.As<v8::Object>();
|
| + if (prototype_object->InternalFieldCount() ==
|
| + kV8PrototypeInternalFieldcount &&
|
| + type->wrapper_type_prototype ==
|
| + WrapperTypeInfo::kWrapperTypeObjectPrototype) {
|
| + prototype_object->SetAlignedPointerInInternalField(
|
| + kV8PrototypeTypeIndex, const_cast<WrapperTypeInfo*>(type));
|
| + }
|
| + type->PreparePrototypeAndInterfaceObject(
|
| + context, world, prototype_object, interface_object, interface_template);
|
| +
|
| + return interface_object;
|
| +}
|
| +
|
| +// NOTE(peria): This method is almost a copy of
|
| +// V8PerContext::CreateWrapperFromCacheSlowCase().
|
| +v8::Local<v8::Object> CreatePlainWrapper(v8::Isolate* isolate,
|
| + const DOMWrapperWorld& world,
|
| + v8::Local<v8::Context> context,
|
| + const WrapperTypeInfo* type) {
|
| + CHECK(V8HTMLDocument::wrapperTypeInfo.Equals(type));
|
| +
|
| + v8::Context::Scope scope(context);
|
| + v8::Local<v8::Function> interface_object =
|
| + ConstructPlainType(isolate, world, context, type);
|
| + CHECK(!interface_object.IsEmpty());
|
| + v8::Local<v8::Object> instance_template;
|
| + CHECK(V8ObjectConstructor::NewInstance(isolate, interface_object)
|
| + .ToLocal(&instance_template));
|
| + v8::Local<v8::Object> wrapper = instance_template->Clone();
|
| + wrapper->SetAlignedPointerInInternalField(kV8DOMWrapperTypeIndex,
|
| + const_cast<WrapperTypeInfo*>(type));
|
| + return wrapper;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +void V8SnapshotCreator::TakeSnapshot(v8::SnapshotCreator* creator,
|
| + int world_id) {
|
| + DCHECK(g_taking_snapshot);
|
| + v8::Isolate* isolate = creator->GetIsolate();
|
| + CHECK_EQ(isolate, v8::Isolate::GetCurrent());
|
| +
|
| + RefPtr<DOMWrapperWorld> world_ptr;
|
| + if (world_id == 0) {
|
| + world_ptr = &DOMWrapperWorld::MainWorld();
|
| + } else {
|
| + world_ptr = DOMWrapperWorld::EnsureIsolatedWorld(isolate, world_id);
|
| + }
|
| + const DOMWrapperWorld& world = *world_ptr;
|
| +
|
| + // Function templates
|
| + v8::HandleScope handleScope(isolate);
|
| + v8::Local<v8::FunctionTemplate> event_target_function_template =
|
| + V8EventTarget::domTemplate(isolate, world);
|
| + CHECK(!event_target_function_template.IsEmpty());
|
| +
|
| + v8::Local<v8::FunctionTemplate> window_function_template =
|
| + V8Window::domTemplate(isolate, world);
|
| + CHECK(!window_function_template.IsEmpty());
|
| +
|
| + v8::Local<v8::FunctionTemplate> node_function_template =
|
| + V8Node::domTemplate(isolate, world);
|
| + CHECK(!node_function_template.IsEmpty());
|
| +
|
| + v8::Local<v8::FunctionTemplate> document_function_template =
|
| + V8Document::domTemplate(isolate, world);
|
| + CHECK(!document_function_template.IsEmpty());
|
| +
|
| + v8::Local<v8::FunctionTemplate> html_document_function_template =
|
| + V8HTMLDocument::domTemplate(isolate, world);
|
| + CHECK(!html_document_function_template.IsEmpty());
|
| +
|
| + v8::Local<v8::ObjectTemplate> window_template =
|
| + window_function_template->InstanceTemplate();
|
| + CHECK(!window_template.IsEmpty());
|
| +
|
| + v8::Local<v8::Context> context;
|
| + v8::Local<v8::Object> wrapper;
|
| + {
|
| + V8PerIsolateData::UseCounterDisabledScope use_counter_disabled(
|
| + V8PerIsolateData::From(isolate));
|
| + context = v8::Context::New(isolate, nullptr, window_template);
|
| + }
|
| + CHECK(!context.IsEmpty());
|
| +
|
| + if (world.IsMainWorld()) {
|
| + context->Enter();
|
| + v8::Context::Scope scope(context);
|
| + wrapper = CreatePlainWrapper(isolate, world, context,
|
| + &V8HTMLDocument::wrapperTypeInfo);
|
| + CHECK(!wrapper.IsEmpty());
|
| + int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex};
|
| + void* values[] = {nullptr, const_cast<WrapperTypeInfo*>(
|
| + &V8HTMLDocument::wrapperTypeInfo)};
|
| + wrapper->SetAlignedPointerInInternalFields(WTF_ARRAY_LENGTH(indices),
|
| + indices, values);
|
| +
|
| + V8PrivateProperty::Symbol symbol =
|
| + V8PrivateProperty::GetWindowDocumentCachedAccessor(isolate);
|
| + CHECK(V8CallBoolean(
|
| + context->Global()->SetPrivate(context, symbol.GetPrivate(), wrapper)));
|
| + context->Exit();
|
| + }
|
| +
|
| + creator->AddTemplate(event_target_function_template);
|
| + creator->AddTemplate(window_function_template);
|
| + creator->AddTemplate(node_function_template);
|
| + creator->AddTemplate(document_function_template);
|
| + creator->AddTemplate(html_document_function_template);
|
| + creator->AddContext(context, Serialize);
|
| +
|
| + V8PerIsolateData::From(isolate)->ClearAll();
|
| + isolate->RemoveMessageListeners(V8Initializer::MessageHandlerInMainThread);
|
| +}
|
| +
|
| +v8::StartupData V8SnapshotCreator::SetUpSnapshotCreator(
|
| + v8::SnapshotCreator* creator) {
|
| + v8::Isolate* isolate = creator->GetIsolate();
|
| + CHECK_EQ(isolate, v8::Isolate::GetCurrent());
|
| +
|
| + // Disable all runtime enabled featuers
|
| + RuntimeEnabledFeatures::setStableFeaturesEnabled(false);
|
| + RuntimeEnabledFeatures::setExperimentalFeaturesEnabled(false);
|
| + RuntimeEnabledFeatures::setTestFeaturesEnabled(false);
|
| +
|
| + {
|
| + v8::HandleScope handleScope(isolate);
|
| + creator->SetDefaultContext(v8::Context::New(isolate));
|
| +
|
| + TakeSnapshot(creator, 0); // main world
|
| + TakeSnapshot(creator, 1); // non main world
|
| + }
|
| +
|
| + return creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
|
| +}
|
| +
|
| +v8::SnapshotCreator* V8SnapshotCreator::GetSnapshotCreator() {
|
| + DCHECK(g_taking_snapshot);
|
| + return V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate())
|
| + ->GetSnapshotCreator();
|
| +}
|
| +
|
| +bool V8SnapshotCreator::TakingSnapshot() {
|
| + return g_taking_snapshot;
|
| +}
|
| +
|
| +void V8SnapshotCreator::SetTakingSnapshot(bool value) {
|
| + g_taking_snapshot = value;
|
| +}
|
| +
|
| +v8::StartupData V8SnapshotCreator::Serialize(v8::Local<v8::Object> holder,
|
| + int index,
|
| + void* /*data*/) {
|
| + FieldType field_type = kNone;
|
| + const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(holder);
|
| + if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) {
|
| + if (kV8DOMWrapperObjectIndex == index) {
|
| + field_type = kHTMLDocumentObject;
|
| + } else if (kV8DOMWrapperTypeIndex == index) {
|
| + field_type = kHTMLDocumentType;
|
| + }
|
| + } else if (blink::V8Document::wrapperTypeInfo.Equals(wrapper_type) &&
|
| + kV8DOMWrapperTypeIndex == index) {
|
| + field_type = kDocumentType;
|
| + } else if (blink::V8Node::wrapperTypeInfo.Equals(wrapper_type) &&
|
| + kV8DOMWrapperTypeIndex == index) {
|
| + field_type = kNodeType;
|
| + }
|
| +
|
| + // To confirm covering all patterns to be serialized.
|
| + CHECK_NE(field_type, kNone);
|
| +
|
| + int size = sizeof(FieldType);
|
| + char* data = new char[size];
|
| + std::memcpy(data, &field_type, size);
|
| +
|
| + return {data, size};
|
| +}
|
| +
|
| +} // namespace blink
|
|
|