OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "bindings/core/v8/V8SnapshotUtil.h" | |
6 | |
7 #include <cstring> | |
8 | |
9 #include "bindings/core/v8/GeneratedCodeHelper.h" | |
10 #include "bindings/core/v8/V8Document.h" | |
11 #include "bindings/core/v8/V8EventTarget.h" | |
12 #include "bindings/core/v8/V8HTMLDocument.h" | |
13 #include "bindings/core/v8/V8Initializer.h" | |
14 #include "bindings/core/v8/V8Node.h" | |
15 #include "bindings/core/v8/V8Window.h" | |
16 #include "platform/bindings/DOMWrapperWorld.h" | |
17 #include "platform/bindings/V8ObjectConstructor.h" | |
18 #include "platform/bindings/V8PerIsolateData.h" | |
19 #include "platform/bindings/V8PrivateProperty.h" | |
20 #include "v8/include/v8.h" | |
21 | |
22 namespace blink { | |
23 | |
24 namespace { | |
25 | |
26 intptr_t* g_snapshot_reference_table = nullptr; | |
27 | |
28 // TODO(peria): This method is almost a copy of | |
29 // V8PerContext::ConstructorForTypeSlowCase(), so merge with it. | |
30 v8::Local<v8::Function> ConstructPlainType(v8::Isolate* isolate, | |
31 const DOMWrapperWorld& world, | |
32 v8::Local<v8::Context> context, | |
33 const WrapperTypeInfo* type) { | |
34 v8::Context::Scope scope(context); | |
35 // We shouldn't reach this point for the types that are implemented in v8 such | |
36 // as typed arrays and hence don't have domTemplateFunction. | |
37 DCHECK(type->dom_template_function); | |
38 v8::Local<v8::FunctionTemplate> interface_template = | |
39 type->domTemplate(isolate, world); | |
40 // Getting the function might fail if we're running out of stack or memory. | |
41 v8::Local<v8::Function> interface_object; | |
42 if (!interface_template->GetFunction(context).ToLocal(&interface_object)) | |
43 return v8::Local<v8::Function>(); | |
44 | |
45 if (type->parent_class) { | |
46 v8::Local<v8::Object> prototype_template = | |
47 ConstructPlainType(isolate, world, context, type->parent_class); | |
48 CHECK(interface_object->SetPrototype(context, prototype_template) | |
49 .ToChecked()); | |
50 } | |
51 | |
52 v8::Local<v8::Value> prototype_value; | |
53 CHECK(interface_object->Get(context, V8AtomicString(isolate, "prototype")) | |
54 .ToLocal(&prototype_value)); | |
55 CHECK(prototype_value->IsObject()); | |
56 v8::Local<v8::Object> prototype_object = prototype_value.As<v8::Object>(); | |
57 if (prototype_object->InternalFieldCount() == | |
58 kV8PrototypeInternalFieldcount && | |
59 type->wrapper_type_prototype == | |
60 WrapperTypeInfo::kWrapperTypeObjectPrototype) { | |
61 prototype_object->SetAlignedPointerInInternalField( | |
62 kV8PrototypeTypeIndex, const_cast<WrapperTypeInfo*>(type)); | |
63 } | |
64 type->PreparePrototypeAndInterfaceObject( | |
65 context, world, prototype_object, interface_object, interface_template); | |
66 | |
67 return interface_object; | |
68 } | |
69 | |
70 // TODO(peria): This method is almost a copy of | |
71 // V8PerContext::CreateWrapperFromCacheSlowCase(), so merge with it. | |
72 v8::Local<v8::Object> CreatePlainWrapper(v8::Isolate* isolate, | |
73 const DOMWrapperWorld& world, | |
74 v8::Local<v8::Context> context, | |
75 const WrapperTypeInfo* type) { | |
76 CHECK(V8HTMLDocument::wrapperTypeInfo.Equals(type)); | |
77 | |
78 v8::Context::Scope scope(context); | |
79 v8::Local<v8::Function> interface_object = | |
80 ConstructPlainType(isolate, world, context, type); | |
81 CHECK(!interface_object.IsEmpty()); | |
82 v8::Local<v8::Object> instance_template; | |
83 CHECK(V8ObjectConstructor::NewInstance(isolate, interface_object) | |
84 .ToLocal(&instance_template)); | |
85 v8::Local<v8::Object> wrapper = instance_template->Clone(); | |
86 wrapper->SetAlignedPointerInInternalField(kV8DOMWrapperTypeIndex, | |
87 const_cast<WrapperTypeInfo*>(type)); | |
88 return wrapper; | |
89 } | |
90 | |
91 constexpr int kWorldIdForNonMainWorld = | |
92 DOMWrapperWorld::WorldId::kIsolatedWorldIdLimit - 1; | |
93 | |
94 int GetSnapshotIndexForWorld(const DOMWrapperWorld& world) { | |
95 return world.IsMainWorld() ? 0 : 1; | |
96 } | |
97 | |
98 constexpr const WrapperTypeInfo* kSnapshotWrapperTypes[] = { | |
99 &V8Window::wrapperTypeInfo, &V8HTMLDocument::wrapperTypeInfo, | |
Yuki
2017/06/20 14:20:11
nit: one entry per line rather than manual spacing
peria
2017/06/21 07:19:16
clang-format does it.
| |
100 &V8EventTarget::wrapperTypeInfo, &V8Node::wrapperTypeInfo, | |
101 &V8Document::wrapperTypeInfo, | |
102 }; | |
103 | |
104 enum class InternalFieldType : uint8_t { | |
105 kNone, | |
106 kNodeType, | |
107 kDocumentType, | |
108 kHTMLDocumentType, | |
109 kHTMLDocumentObject, | |
110 }; | |
111 | |
112 const WrapperTypeInfo* FieldTypeToWrapperTypeInfo(InternalFieldType type) { | |
113 switch (type) { | |
114 case InternalFieldType::kNone: | |
115 NOTREACHED(); | |
116 break; | |
117 case InternalFieldType::kNodeType: | |
118 return &V8Node::wrapperTypeInfo; | |
119 case InternalFieldType::kDocumentType: | |
120 return &V8Document::wrapperTypeInfo; | |
121 case InternalFieldType::kHTMLDocumentType: | |
122 return &V8HTMLDocument::wrapperTypeInfo; | |
123 case InternalFieldType::kHTMLDocumentObject: | |
124 return &V8HTMLDocument::wrapperTypeInfo; | |
125 } | |
126 NOTREACHED(); | |
127 return nullptr; | |
128 } | |
129 | |
130 struct DataForDeserializer { | |
131 STACK_ALLOCATED(); | |
132 Member<Document> document; | |
133 }; | |
134 | |
135 int CountExternalReferenceEntries() { | |
136 if (!g_snapshot_reference_table) | |
137 return 0; | |
138 | |
139 // To ignore the terminate entry '0'. | |
Yuki
2017/06/20 14:20:11
It seems that you're not counting the null termina
peria
2017/06/21 07:19:16
Done.
| |
140 int count = -1; | |
141 for (intptr_t* p = g_snapshot_reference_table; *p; ++p) | |
142 ++count; | |
143 return count; | |
144 } | |
145 | |
146 } // namespace | |
147 | |
148 v8::StartupData V8SnapshotUtil::TakeSnapshot() { | |
149 DCHECK_EQ(V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate()) | |
150 ->GetV8ContextMode(), | |
151 V8PerIsolateData::V8ContextMode::kTakeSnapshot); | |
152 | |
153 v8::SnapshotCreator* creator = | |
154 V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate()) | |
155 ->GetSnapshotCreator(); | |
156 v8::Isolate* isolate = creator->GetIsolate(); | |
157 CHECK_EQ(isolate, v8::Isolate::GetCurrent()); | |
158 | |
159 LOG(INFO) << "External reference table has " | |
160 << CountExternalReferenceEntries() << " entries."; | |
161 | |
162 // Disable all runtime enabled featuers | |
163 RuntimeEnabledFeatures::SetStableFeaturesEnabled(false); | |
164 RuntimeEnabledFeatures::SetExperimentalFeaturesEnabled(false); | |
165 RuntimeEnabledFeatures::SetTestFeaturesEnabled(false); | |
166 | |
167 { | |
168 v8::HandleScope handleScope(isolate); | |
169 creator->SetDefaultContext(v8::Context::New(isolate)); | |
170 | |
171 TakeSnapshotForWorld(creator, DOMWrapperWorld::MainWorld()); | |
172 // For non main worlds, we can use any type to create a context. | |
173 TakeSnapshotForWorld(creator, *DOMWrapperWorld::EnsureIsolatedWorld( | |
174 isolate, kWorldIdForNonMainWorld)); | |
175 } | |
176 | |
177 // Snapshot is taken on the main thread, but it can be used on other threads. | |
178 // So we remove a message handler for the main thread. | |
179 isolate->RemoveMessageListeners(V8Initializer::MessageHandlerInMainThread); | |
180 | |
181 return creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); | |
182 } | |
183 | |
184 void V8SnapshotUtil::TakeSnapshotForWorld(v8::SnapshotCreator* creator, | |
185 const DOMWrapperWorld& world) { | |
186 v8::Isolate* isolate = creator->GetIsolate(); | |
187 CHECK_EQ(isolate, v8::Isolate::GetCurrent()); | |
188 | |
189 // Function templates | |
190 v8::HandleScope handleScope(isolate); | |
191 Vector<v8::Local<v8::FunctionTemplate>> interface_templates; | |
192 for (const WrapperTypeInfo* wrapper_type_info : kSnapshotWrapperTypes) { | |
193 v8::Local<v8::FunctionTemplate> interface_template = | |
194 wrapper_type_info->domTemplate(isolate, world); | |
195 CHECK(!interface_template.IsEmpty()); | |
196 interface_templates.push_back(interface_template); | |
197 } | |
198 | |
199 // FIXME: Confirm interface_tempaltes[0] is a template of V8Window. | |
Yuki
2017/06/20 14:20:11
s/FIXME/TODO(peria)/
peria
2017/06/21 07:19:16
Done.
| |
200 v8::Local<v8::ObjectTemplate> window_template = | |
201 interface_templates[0]->InstanceTemplate(); | |
202 CHECK(!window_template.IsEmpty()); | |
203 | |
204 v8::Local<v8::Context> context; | |
205 { | |
206 V8PerIsolateData::UseCounterDisabledScope use_counter_disabled( | |
207 V8PerIsolateData::From(isolate)); | |
208 context = v8::Context::New(isolate, nullptr, window_template); | |
209 } | |
210 CHECK(!context.IsEmpty()); | |
211 | |
212 if (world.IsMainWorld()) { | |
213 v8::Context::Scope scope(context); | |
214 v8::Local<v8::Object> document_wrapper = CreatePlainWrapper( | |
215 isolate, world, context, &V8HTMLDocument::wrapperTypeInfo); | |
216 int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex}; | |
217 void* values[] = {nullptr, const_cast<WrapperTypeInfo*>( | |
218 &V8HTMLDocument::wrapperTypeInfo)}; | |
219 document_wrapper->SetAlignedPointerInInternalFields( | |
220 WTF_ARRAY_LENGTH(indices), indices, values); | |
221 | |
222 // Update the cached accessor for window.document. | |
223 CHECK(V8PrivateProperty::GetWindowDocumentCachedAccessor(isolate).Set( | |
224 context->Global(), document_wrapper)); | |
225 } | |
226 | |
227 for (auto& interface_template : interface_templates) { | |
228 creator->AddTemplate(interface_template); | |
229 } | |
230 creator->AddContext(context, SerializeInternalField); | |
231 | |
232 V8PerIsolateData::From(isolate)->ClearPersistentsForV8Snapshot(); | |
233 } | |
234 | |
235 void V8SnapshotUtil::EnsureInterfaceTemplates(v8::Isolate* isolate) { | |
236 if (V8PerIsolateData::From(isolate)->GetV8ContextMode() != | |
237 V8PerIsolateData::V8ContextMode::kUseSnapshot) { | |
238 return; | |
239 } | |
240 | |
241 EnsureInterfaceTemplatesForWorld(isolate, DOMWrapperWorld::MainWorld()); | |
242 EnsureInterfaceTemplatesForWorld( | |
243 isolate, | |
244 *DOMWrapperWorld::EnsureIsolatedWorld(isolate, kWorldIdForNonMainWorld)); | |
245 } | |
246 | |
247 void V8SnapshotUtil::EnsureInterfaceTemplatesForWorld( | |
248 v8::Isolate* isolate, | |
249 const DOMWrapperWorld& world) { | |
250 for (const WrapperTypeInfo* wrapper_type_info : kSnapshotWrapperTypes) { | |
251 v8::Local<v8::FunctionTemplate> interface = | |
252 wrapper_type_info->domTemplate(isolate, world); | |
253 CHECK(!interface.IsEmpty()); | |
254 } | |
255 } | |
256 | |
257 v8::Local<v8::FunctionTemplate> V8SnapshotUtil::InterfaceTemplateFromSnapshot( | |
258 v8::Isolate* isolate, | |
259 const DOMWrapperWorld& world, | |
260 WrapperTypeInfo* wrapper_type_info) { | |
261 if (V8PerIsolateData::From(isolate)->GetV8ContextMode() != | |
262 V8PerIsolateData::V8ContextMode::kUseSnapshot) { | |
263 return v8::Local<v8::FunctionTemplate>(); | |
264 } | |
265 | |
266 const int index_offset = | |
267 world.IsMainWorld() ? 0 : WTF_ARRAY_LENGTH(kSnapshotWrapperTypes); | |
268 | |
269 // Snapshotted templates are expected to be used just to get | |
270 // wrapper_type_info. | |
271 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kSnapshotWrapperTypes); ++i) { | |
272 if (kSnapshotWrapperTypes[i]->Equals(wrapper_type_info)) { | |
273 return v8::FunctionTemplate::FromSnapshot(isolate, index_offset + i) | |
274 .ToLocalChecked(); | |
275 } | |
276 } | |
277 return v8::Local<v8::FunctionTemplate>(); | |
278 } | |
279 | |
280 v8::StartupData V8SnapshotUtil::SerializeInternalField( | |
281 v8::Local<v8::Object> holder, | |
282 int index, | |
283 void*) { | |
284 InternalFieldType field_type = InternalFieldType::kNone; | |
285 const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(holder); | |
286 if (kV8DOMWrapperObjectIndex == index) { | |
287 if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) { | |
288 field_type = InternalFieldType::kHTMLDocumentObject; | |
289 } | |
290 } else if (kV8DOMWrapperTypeIndex == index) { | |
291 if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) { | |
292 field_type = InternalFieldType::kHTMLDocumentType; | |
293 } else if (blink::V8Document::wrapperTypeInfo.Equals(wrapper_type)) { | |
294 field_type = InternalFieldType::kDocumentType; | |
295 } else if (blink::V8Node::wrapperTypeInfo.Equals(wrapper_type)) { | |
296 field_type = InternalFieldType::kNodeType; | |
297 } | |
298 } | |
299 CHECK_NE(field_type, InternalFieldType::kNone); | |
300 | |
301 int size = sizeof(InternalFieldType); | |
302 char* data = new char[size]; | |
303 std::memcpy(data, &field_type, size); | |
304 | |
305 return {data, size}; | |
306 } | |
307 | |
308 void V8SnapshotUtil::DeserializeInternalField(v8::Local<v8::Object> holder, | |
309 int index, | |
310 v8::StartupData payload, | |
311 void* ptr) { | |
312 // DeserializeInternalField() expects to be called in the main world | |
313 // with |document| being HTMLDocument. | |
314 CHECK_EQ(payload.raw_size, static_cast<int>(sizeof(InternalFieldType))); | |
315 InternalFieldType type = | |
316 *reinterpret_cast<const InternalFieldType*>(payload.data); | |
317 | |
318 const WrapperTypeInfo* wrapper_type_info = FieldTypeToWrapperTypeInfo(type); | |
319 switch (type) { | |
320 case InternalFieldType::kNodeType: | |
321 case InternalFieldType::kDocumentType: | |
322 case InternalFieldType::kHTMLDocumentType: { | |
323 CHECK_EQ(index, kV8DOMWrapperTypeIndex); | |
324 holder->SetAlignedPointerInInternalField( | |
325 index, const_cast<WrapperTypeInfo*>(wrapper_type_info)); | |
326 return; | |
327 } | |
328 case InternalFieldType::kHTMLDocumentObject: { | |
329 CHECK_EQ(index, kV8DOMWrapperObjectIndex); | |
330 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | |
331 DataForDeserializer* data = static_cast<DataForDeserializer*>(ptr); | |
332 ScriptWrappable* document = data->document; | |
333 DCHECK(document); | |
334 | |
335 // Make reference from wrapper to document | |
336 holder->SetAlignedPointerInInternalField(index, document); | |
337 // Make reference from document to wrapper | |
338 CHECK(document->SetWrapper(isolate, wrapper_type_info, holder)); | |
339 WrapperTypeInfo::WrapperCreated(); | |
340 return; | |
341 } | |
342 case InternalFieldType::kNone: | |
343 NOTREACHED(); | |
344 return; | |
345 } | |
346 | |
347 NOTREACHED(); | |
348 } | |
349 | |
350 v8::Local<v8::Context> V8SnapshotUtil::CreateContext( | |
351 v8::Isolate* isolate, | |
352 const DOMWrapperWorld& world, | |
353 v8::ExtensionConfiguration* extension_configuration, | |
354 v8::Local<v8::Object> global_proxy, | |
355 Document* document) { | |
356 if (V8PerIsolateData::From(isolate)->GetV8ContextMode() != | |
357 V8PerIsolateData::V8ContextMode::kUseSnapshot) { | |
358 return v8::Local<v8::Context>(); | |
359 } | |
360 // For main world frames, a HTMLDocument object is required to be | |
361 // deserialized. | |
362 if (world.IsMainWorld() && !(document && document->IsHTMLDocument())) { | |
363 return v8::Local<v8::Context>(); | |
364 } | |
365 const int index = GetSnapshotIndexForWorld(world); | |
366 DataForDeserializer data{document}; | |
367 v8::DeserializeInternalFieldsCallback callback = | |
368 v8::DeserializeInternalFieldsCallback(&DeserializeInternalField, &data); | |
369 v8::Local<v8::Context> context = | |
370 v8::Context::FromSnapshot(isolate, index, callback, | |
371 extension_configuration, global_proxy) | |
372 .ToLocalChecked(); | |
373 CHECK(!context.IsEmpty()); | |
374 | |
375 if (world.IsMainWorld()) { | |
376 v8::Context::Scope scope(context); | |
377 v8::Local<v8::Object> wrapper = document->MainWorldWrapper(isolate); | |
378 CHECK(!wrapper.IsEmpty()); | |
379 v8::Local<v8::Object> empty_prototype; | |
380 v8::Local<v8::Function> empty_interface; | |
381 | |
382 V8HTMLDocument::InstallRuntimeEnabledFeatures( | |
383 isolate, world, wrapper, empty_prototype, empty_interface); | |
384 V8Document::InstallRuntimeEnabledFeatures(isolate, world, wrapper, | |
385 empty_prototype, empty_interface); | |
386 V8Node::InstallRuntimeEnabledFeatures(isolate, world, wrapper, | |
387 empty_prototype, empty_interface); | |
388 V8EventTarget::InstallRuntimeEnabledFeatures( | |
389 isolate, world, wrapper, empty_prototype, empty_interface); | |
390 } | |
391 return context; | |
392 } | |
393 | |
394 void V8SnapshotUtil::SetupContext(v8::Local<v8::Context> context) { | |
395 ScriptState* script_state = ScriptState::From(context); | |
396 v8::Isolate* isolate = script_state->GetIsolate(); | |
397 if (V8PerIsolateData::From(isolate)->GetV8ContextMode() != | |
398 V8PerIsolateData::V8ContextMode::kUseSnapshot) { | |
399 return; | |
400 } | |
401 | |
402 DOMWrapperWorld& world = script_state->World(); | |
403 V8PerContextData* data = script_state->PerContextData(); | |
404 | |
405 v8::Local<v8::Object> empty_prototype; | |
406 v8::Local<v8::Function> empty_interface; | |
407 // Set up Window wrapper. | |
408 { | |
409 v8::Local<v8::Object> global_proxy = context->Global(); | |
410 v8::Local<v8::Object> wrapper = | |
411 global_proxy->GetPrototype().As<v8::Object>(); | |
412 V8Window::installV8WindowRuntimeEnabledFunction( | |
413 isolate, world, wrapper, empty_prototype, empty_interface); | |
414 V8EventTarget::InstallRuntimeEnabledFeatures( | |
415 isolate, world, wrapper, empty_prototype, empty_interface); | |
416 } | |
417 | |
418 // Setup V8PerContextData::constructor_map_ and wrapper_boilerplate_. | |
419 { | |
420 const WrapperTypeInfo* type = &V8EventTarget::wrapperTypeInfo; | |
421 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
422 v8::Local<v8::Object> prototype = | |
423 constructor->Get(context, V8AtomicString(isolate, "prototype")) | |
424 .ToLocalChecked() | |
425 .As<v8::Object>(); | |
426 v8::Local<v8::Object> wrapper = data->CreateWrapperFromCache(type); | |
427 V8EventTarget::InstallRuntimeEnabledFeatures(isolate, world, wrapper, | |
428 prototype, constructor); | |
429 data->constructor_map_.Set(type, constructor); | |
430 data->wrapper_boilerplates_.Set(type, wrapper); | |
431 } | |
432 { | |
433 const WrapperTypeInfo* type = &V8Window::wrapperTypeInfo; | |
434 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
435 v8::Local<v8::Object> prototype = | |
436 constructor->Get(context, V8AtomicString(isolate, "prototype")) | |
437 .ToLocalChecked() | |
438 .As<v8::Object>(); | |
439 v8::Local<v8::Object> wrapper = data->CreateWrapperFromCache(type); | |
440 V8Window::installV8WindowRuntimeEnabledFunction(isolate, world, wrapper, | |
441 prototype, constructor); | |
442 V8EventTarget::InstallRuntimeEnabledFeatures( | |
443 isolate, world, wrapper, empty_prototype, empty_interface); | |
444 data->constructor_map_.Set(type, constructor); | |
445 data->wrapper_boilerplates_.Set(type, wrapper); | |
446 } | |
447 { | |
448 const WrapperTypeInfo* type = &V8Node::wrapperTypeInfo; | |
449 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
450 v8::Local<v8::Object> prototype = | |
451 constructor->Get(context, V8AtomicString(isolate, "prototype")) | |
452 .ToLocalChecked() | |
453 .As<v8::Object>(); | |
454 v8::Local<v8::Object> wrapper = data->CreateWrapperFromCache(type); | |
455 V8Node::InstallRuntimeEnabledFeatures(isolate, world, wrapper, prototype, | |
456 constructor); | |
457 V8EventTarget::InstallRuntimeEnabledFeatures( | |
458 isolate, world, wrapper, empty_prototype, empty_interface); | |
459 data->constructor_map_.Set(type, constructor); | |
460 data->wrapper_boilerplates_.Set(type, wrapper); | |
461 } | |
462 { | |
463 const WrapperTypeInfo* type = &V8Document::wrapperTypeInfo; | |
464 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
465 v8::Local<v8::Object> prototype = | |
466 constructor->Get(context, V8AtomicString(isolate, "prototype")) | |
467 .ToLocalChecked() | |
468 .As<v8::Object>(); | |
469 v8::Local<v8::Object> wrapper = data->CreateWrapperFromCache(type); | |
470 V8Document::InstallRuntimeEnabledFeatures(isolate, world, wrapper, | |
471 prototype, constructor); | |
472 V8Node::InstallRuntimeEnabledFeatures(isolate, world, wrapper, | |
473 empty_prototype, empty_interface); | |
474 V8EventTarget::InstallRuntimeEnabledFeatures( | |
475 isolate, world, wrapper, empty_prototype, empty_interface); | |
476 data->constructor_map_.Set(type, constructor); | |
477 data->wrapper_boilerplates_.Set(type, wrapper); | |
478 } | |
479 { | |
480 const WrapperTypeInfo* type = &V8HTMLDocument::wrapperTypeInfo; | |
481 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
482 v8::Local<v8::Object> prototype = | |
483 constructor->Get(context, V8AtomicString(isolate, "prototype")) | |
484 .ToLocalChecked() | |
485 .As<v8::Object>(); | |
486 v8::Local<v8::Object> wrapper = data->CreateWrapperFromCache(type); | |
487 V8HTMLDocument::InstallRuntimeEnabledFeatures(isolate, world, wrapper, | |
488 prototype, constructor); | |
489 V8Document::InstallRuntimeEnabledFeatures(isolate, world, wrapper, | |
490 empty_prototype, empty_interface); | |
491 V8Node::InstallRuntimeEnabledFeatures(isolate, world, wrapper, | |
492 empty_prototype, empty_interface); | |
493 V8EventTarget::InstallRuntimeEnabledFeatures( | |
494 isolate, world, wrapper, empty_prototype, empty_interface); | |
495 data->constructor_map_.Set(type, constructor); | |
496 data->wrapper_boilerplates_.Set(type, wrapper); | |
497 } | |
498 } | |
499 | |
500 void V8SnapshotUtil::SetReferenceTable(intptr_t* table) { | |
501 DCHECK(!g_snapshot_reference_table); | |
502 g_snapshot_reference_table = table; | |
503 } | |
504 | |
505 intptr_t* V8SnapshotUtil::GetReferenceTable() { | |
506 DCHECK(g_snapshot_reference_table); | |
507 return g_snapshot_reference_table; | |
508 } | |
509 | |
510 } // namespace blink | |
OLD | NEW |