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)) | |
Yuki
2017/06/23 15:20:45
s/ToLocal/ToLocalChecked/
peria
2017/06/27 09:52:37
Done.
| |
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)); | |
Yuki
2017/06/23 15:20:44
s/CHECK(...ToLocal(...))/ToLocalChecked()/
peria
2017/06/27 09:52:37
Done.
| |
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)); | |
Yuki
2017/06/23 15:20:44
s/CHECK(...ToLocal(...))/ToLocalChecked()/
peria
2017/06/27 09:52:37
Done.
| |
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, | |
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 int count = 0; | |
140 for (intptr_t* p = g_snapshot_reference_table; *p; ++p) | |
141 ++count; | |
142 return count; | |
143 } | |
144 | |
145 } // namespace | |
146 | |
147 v8::StartupData V8SnapshotUtil::TakeSnapshot() { | |
148 DCHECK_EQ(V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate()) | |
149 ->GetV8ContextMode(), | |
150 V8PerIsolateData::V8ContextMode::kTakeSnapshot); | |
151 | |
152 v8::SnapshotCreator* creator = | |
153 V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate()) | |
154 ->GetSnapshotCreator(); | |
155 v8::Isolate* isolate = creator->GetIsolate(); | |
156 CHECK_EQ(isolate, v8::Isolate::GetCurrent()); | |
157 | |
158 VLOG(1) << "External reference table has " << CountExternalReferenceEntries() | |
159 << " entries."; | |
160 | |
161 // Disable all runtime enabled featuers | |
162 RuntimeEnabledFeatures::SetStableFeaturesEnabled(false); | |
163 RuntimeEnabledFeatures::SetExperimentalFeaturesEnabled(false); | |
164 RuntimeEnabledFeatures::SetTestFeaturesEnabled(false); | |
165 | |
166 { | |
167 v8::HandleScope handleScope(isolate); | |
168 creator->SetDefaultContext(v8::Context::New(isolate)); | |
169 | |
170 TakeSnapshotForWorld(creator, DOMWrapperWorld::MainWorld()); | |
171 // For non main worlds, we can use any type to create a context. | |
172 TakeSnapshotForWorld(creator, *DOMWrapperWorld::EnsureIsolatedWorld( | |
173 isolate, kWorldIdForNonMainWorld)); | |
174 } | |
175 | |
176 // Snapshot is taken on the main thread, but it can be used on other threads. | |
177 // So we remove a message handler for the main thread. | |
178 isolate->RemoveMessageListeners(V8Initializer::MessageHandlerInMainThread); | |
179 | |
180 return creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); | |
181 } | |
182 | |
183 void V8SnapshotUtil::TakeSnapshotForWorld(v8::SnapshotCreator* creator, | |
Yuki
2017/06/23 15:20:45
Be consistent with the declaration order in the he
peria
2017/06/27 09:52:37
Done.
| |
184 const DOMWrapperWorld& world) { | |
185 v8::Isolate* isolate = creator->GetIsolate(); | |
186 CHECK_EQ(isolate, v8::Isolate::GetCurrent()); | |
187 | |
188 // Function templates | |
189 v8::HandleScope handleScope(isolate); | |
190 Vector<v8::Local<v8::FunctionTemplate>> interface_templates; | |
Yuki
2017/06/23 15:20:45
It's not allowed to put v8::Local on heap. Vector
peria
2017/06/27 09:52:37
Done.
| |
191 for (const WrapperTypeInfo* wrapper_type_info : kSnapshotWrapperTypes) { | |
192 v8::Local<v8::FunctionTemplate> interface_template = | |
193 wrapper_type_info->domTemplate(isolate, world); | |
194 CHECK(!interface_template.IsEmpty()); | |
195 interface_templates.push_back(interface_template); | |
196 } | |
197 | |
198 // TODO(peria): Confirm interface_tempaltes[0] is a template of V8Window. | |
199 v8::Local<v8::ObjectTemplate> window_template = | |
200 interface_templates[0]->InstanceTemplate(); | |
201 CHECK(!window_template.IsEmpty()); | |
202 | |
203 v8::Local<v8::Context> context; | |
204 { | |
205 V8PerIsolateData::UseCounterDisabledScope use_counter_disabled( | |
206 V8PerIsolateData::From(isolate)); | |
207 context = v8::Context::New(isolate, nullptr, window_template); | |
208 } | |
209 CHECK(!context.IsEmpty()); | |
210 | |
211 if (world.IsMainWorld()) { | |
212 v8::Context::Scope scope(context); | |
213 v8::Local<v8::Object> document_wrapper = CreatePlainWrapper( | |
214 isolate, world, context, &V8HTMLDocument::wrapperTypeInfo); | |
215 int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex}; | |
216 void* values[] = {nullptr, const_cast<WrapperTypeInfo*>( | |
217 &V8HTMLDocument::wrapperTypeInfo)}; | |
218 document_wrapper->SetAlignedPointerInInternalFields( | |
219 WTF_ARRAY_LENGTH(indices), indices, values); | |
220 | |
221 // Update the cached accessor for window.document. | |
222 CHECK(V8PrivateProperty::GetWindowDocumentCachedAccessor(isolate).Set( | |
Yuki
2017/06/23 15:20:44
Probably, this should be gone.
You're now setting
peria
2017/06/27 09:52:37
Hmm. This code is required here to keep the HTMLDo
| |
223 context->Global(), document_wrapper)); | |
224 } | |
225 | |
226 for (auto& interface_template : interface_templates) { | |
227 creator->AddTemplate(interface_template); | |
228 } | |
229 creator->AddContext(context, SerializeInternalField); | |
230 | |
231 V8PerIsolateData::From(isolate)->ClearPersistentsForV8Snapshot(); | |
232 } | |
233 | |
234 void V8SnapshotUtil::EnsureInterfaceTemplates(v8::Isolate* isolate) { | |
235 if (V8PerIsolateData::From(isolate)->GetV8ContextMode() != | |
236 V8PerIsolateData::V8ContextMode::kUseSnapshot) { | |
237 return; | |
238 } | |
239 | |
240 EnsureInterfaceTemplatesForWorld(isolate, DOMWrapperWorld::MainWorld()); | |
241 EnsureInterfaceTemplatesForWorld( | |
242 isolate, | |
243 *DOMWrapperWorld::EnsureIsolatedWorld(isolate, kWorldIdForNonMainWorld)); | |
244 } | |
245 | |
246 void V8SnapshotUtil::EnsureInterfaceTemplatesForWorld( | |
247 v8::Isolate* isolate, | |
248 const DOMWrapperWorld& world) { | |
249 V8PerIsolateData* data = V8PerIsolateData::From(isolate); | |
250 for (const WrapperTypeInfo* wrapper_type_info : kSnapshotWrapperTypes) { | |
251 v8::Local<v8::FunctionTemplate> interface = | |
252 InterfaceTemplateFromSnapshot(isolate, world, wrapper_type_info); | |
253 CHECK(!interface.IsEmpty()); | |
254 data->SetInterfaceTemplate(world, wrapper_type_info, interface); | |
255 } | |
256 } | |
257 | |
258 v8::Local<v8::FunctionTemplate> V8SnapshotUtil::InterfaceTemplateFromSnapshot( | |
Yuki
2017/06/23 15:20:44
InterfaceTemplateFromSnapshot is only used in Ensu
peria
2017/06/27 09:52:37
Done.
| |
259 v8::Isolate* isolate, | |
260 const DOMWrapperWorld& world, | |
261 const WrapperTypeInfo* wrapper_type_info) { | |
262 const int index_offset = | |
263 world.IsMainWorld() ? 0 : WTF_ARRAY_LENGTH(kSnapshotWrapperTypes); | |
264 | |
265 if (V8Window::wrapperTypeInfo.Equals(wrapper_type_info)) { | |
266 v8::Local<v8::FunctionTemplate> interface_template = | |
267 v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 0) | |
268 .ToLocalChecked(); | |
269 V8Window::installV8WindowRuntimeEnabledOnTemplateFunction( | |
Yuki
2017/06/23 15:20:44
s/installV8Window.../InstallV8Window.../
Does thi
peria
2017/06/27 09:52:37
For V8Window, we call it via static function point
| |
270 isolate, world, interface_template); | |
271 return interface_template; | |
272 } | |
273 if (V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type_info)) { | |
274 v8::Local<v8::FunctionTemplate> interface_template = | |
275 v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 1) | |
276 .ToLocalChecked(); | |
277 V8HTMLDocument::InstallRuntimeEnabledFeaturesOnTemplate(isolate, world, | |
278 interface_template); | |
279 return interface_template; | |
280 } | |
281 if (V8EventTarget::wrapperTypeInfo.Equals(wrapper_type_info)) { | |
282 v8::Local<v8::FunctionTemplate> interface_template = | |
283 v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 2) | |
284 .ToLocalChecked(); | |
285 V8EventTarget::InstallRuntimeEnabledFeaturesOnTemplate(isolate, world, | |
286 interface_template); | |
287 return interface_template; | |
288 } | |
289 if (V8Node::wrapperTypeInfo.Equals(wrapper_type_info)) { | |
290 v8::Local<v8::FunctionTemplate> interface_template = | |
291 v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 3) | |
292 .ToLocalChecked(); | |
293 V8Node::InstallRuntimeEnabledFeaturesOnTemplate(isolate, world, | |
294 interface_template); | |
295 return interface_template; | |
296 } | |
297 if (V8Document::wrapperTypeInfo.Equals(wrapper_type_info)) { | |
298 v8::Local<v8::FunctionTemplate> interface_template = | |
299 v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 4) | |
300 .ToLocalChecked(); | |
301 V8Document::InstallRuntimeEnabledFeaturesOnTemplate(isolate, world, | |
302 interface_template); | |
303 return interface_template; | |
304 } | |
305 | |
306 NOTREACHED(); | |
307 return v8::Local<v8::FunctionTemplate>(); | |
308 } | |
309 | |
310 v8::StartupData V8SnapshotUtil::SerializeInternalField( | |
311 v8::Local<v8::Object> holder, | |
312 int index, | |
313 void*) { | |
314 InternalFieldType field_type = InternalFieldType::kNone; | |
315 const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(holder); | |
316 if (kV8DOMWrapperObjectIndex == index) { | |
317 if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) { | |
318 field_type = InternalFieldType::kHTMLDocumentObject; | |
319 } | |
320 } else if (kV8DOMWrapperTypeIndex == index) { | |
321 if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) { | |
322 field_type = InternalFieldType::kHTMLDocumentType; | |
323 } else if (blink::V8Document::wrapperTypeInfo.Equals(wrapper_type)) { | |
324 field_type = InternalFieldType::kDocumentType; | |
325 } else if (blink::V8Node::wrapperTypeInfo.Equals(wrapper_type)) { | |
326 field_type = InternalFieldType::kNodeType; | |
327 } | |
328 } | |
329 CHECK_NE(field_type, InternalFieldType::kNone); | |
330 | |
331 int size = sizeof(InternalFieldType); | |
332 char* data = new char[size]; | |
333 std::memcpy(data, &field_type, size); | |
334 | |
335 return {data, size}; | |
336 } | |
337 | |
338 void V8SnapshotUtil::DeserializeInternalField(v8::Local<v8::Object> holder, | |
Yuki
2017/06/23 15:20:44
s/holder/object/
This is not relevant to a holder
peria
2017/06/27 09:52:37
Done.
| |
339 int index, | |
340 v8::StartupData payload, | |
341 void* ptr) { | |
342 // DeserializeInternalField() expects to be called in the main world | |
343 // with |document| being HTMLDocument. | |
344 CHECK_EQ(payload.raw_size, static_cast<int>(sizeof(InternalFieldType))); | |
345 InternalFieldType type = | |
346 *reinterpret_cast<const InternalFieldType*>(payload.data); | |
347 | |
348 const WrapperTypeInfo* wrapper_type_info = FieldTypeToWrapperTypeInfo(type); | |
349 switch (type) { | |
350 case InternalFieldType::kNodeType: | |
351 case InternalFieldType::kDocumentType: | |
352 case InternalFieldType::kHTMLDocumentType: { | |
353 CHECK_EQ(index, kV8DOMWrapperTypeIndex); | |
354 holder->SetAlignedPointerInInternalField( | |
355 index, const_cast<WrapperTypeInfo*>(wrapper_type_info)); | |
356 return; | |
357 } | |
358 case InternalFieldType::kHTMLDocumentObject: { | |
359 CHECK_EQ(index, kV8DOMWrapperObjectIndex); | |
360 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | |
361 DataForDeserializer* data = static_cast<DataForDeserializer*>(ptr); | |
362 ScriptWrappable* document = data->document; | |
363 DCHECK(document); | |
364 | |
365 // Make reference from wrapper to document | |
366 holder->SetAlignedPointerInInternalField(index, document); | |
367 // Make reference from document to wrapper | |
368 CHECK(document->SetWrapper(isolate, wrapper_type_info, holder)); | |
369 WrapperTypeInfo::WrapperCreated(); | |
370 return; | |
371 } | |
372 case InternalFieldType::kNone: | |
373 NOTREACHED(); | |
374 return; | |
375 } | |
376 | |
377 NOTREACHED(); | |
378 } | |
379 | |
380 v8::Local<v8::Context> V8SnapshotUtil::CreateContext( | |
381 v8::Isolate* isolate, | |
382 const DOMWrapperWorld& world, | |
383 v8::ExtensionConfiguration* extension_configuration, | |
384 v8::Local<v8::Object> global_proxy, | |
385 Document* document) { | |
386 if (V8PerIsolateData::From(isolate)->GetV8ContextMode() != | |
387 V8PerIsolateData::V8ContextMode::kUseSnapshot) { | |
388 return v8::Local<v8::Context>(); | |
389 } | |
390 // For main world frames, we don't support the case that |document| is not | |
391 // an instance of HTMLDocument, e.g. XMLDocument. | |
392 if (world.IsMainWorld() && !(document && document->IsHTMLDocument())) { | |
393 return v8::Local<v8::Context>(); | |
394 } | |
395 const int index = GetSnapshotIndexForWorld(world); | |
396 DataForDeserializer data{document}; | |
397 v8::DeserializeInternalFieldsCallback callback = | |
398 v8::DeserializeInternalFieldsCallback(&DeserializeInternalField, &data); | |
399 v8::Local<v8::Context> context = | |
400 v8::Context::FromSnapshot(isolate, index, callback, | |
401 extension_configuration, global_proxy) | |
402 .ToLocalChecked(); | |
403 CHECK(!context.IsEmpty()); | |
404 DVLOG(1) << "A context is created from snapshot"; | |
405 | |
406 return context; | |
407 } | |
408 | |
409 void V8SnapshotUtil::SetupContext(v8::Local<v8::Context> context, | |
410 Document* document) { | |
411 ScriptState* script_state = ScriptState::From(context); | |
412 v8::Isolate* isolate = script_state->GetIsolate(); | |
413 if (V8PerIsolateData::From(isolate)->GetV8ContextMode() != | |
414 V8PerIsolateData::V8ContextMode::kUseSnapshot) { | |
415 return; | |
416 } | |
417 | |
418 v8::Local<v8::String> prototype_str = V8AtomicString(isolate, "prototype"); | |
419 DOMWrapperWorld& world = script_state->World(); | |
420 V8PerContextData* data = script_state->PerContextData(); | |
421 | |
422 v8::Local<v8::Object> global_proxy = context->Global(); | |
423 v8::Local<v8::Object> window_wrapper = | |
424 global_proxy->GetPrototype().As<v8::Object>(); | |
425 { | |
426 const WrapperTypeInfo* type = &V8EventTarget::wrapperTypeInfo; | |
427 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
Yuki
2017/06/23 15:20:44
nit: s/constructor/interface/
We're not intereste
peria
2017/06/27 09:52:37
Done.
| |
428 v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str) | |
429 .ToLocalChecked() | |
430 .As<v8::Object>(); | |
431 V8EventTarget::InstallRuntimeEnabledFeatures(isolate, world, window_wrapper, | |
432 prototype, constructor); | |
433 } | |
434 { | |
435 const WrapperTypeInfo* type = &V8Window::wrapperTypeInfo; | |
436 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
437 v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str) | |
438 .ToLocalChecked() | |
439 .As<v8::Object>(); | |
440 V8Window::installV8WindowRuntimeEnabledFunction( | |
441 isolate, world, window_wrapper, prototype, constructor); | |
442 } | |
443 | |
444 // In case we create a context for the main world from snapshot, we also have | |
445 // to work for HTMLDocument wrapper and its prototype chain. | |
446 if (world.IsMainWorld() && document && document->IsHTMLDocument()) { | |
Yuki
2017/06/23 15:20:44
This condition must appear at the very beginning o
peria
2017/06/27 09:52:37
Done.
| |
447 CHECK(document->ContainsWrapper()); | |
448 v8::Local<v8::Object> document_wrapper = | |
449 document->MainWorldWrapper(isolate); | |
450 | |
451 { | |
452 // Prototype object and interface object of EventTarget were set up with | |
453 // Window wrapper. | |
454 V8EventTarget::InstallRuntimeEnabledFeatures( | |
455 isolate, world, document_wrapper, v8::Local<v8::Object>(), | |
456 v8::Local<v8::Function>()); | |
457 } | |
458 { | |
459 const WrapperTypeInfo* type = &V8Node::wrapperTypeInfo; | |
460 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
461 v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str) | |
462 .ToLocalChecked() | |
463 .As<v8::Object>(); | |
464 V8Node::InstallRuntimeEnabledFeatures(isolate, world, document_wrapper, | |
465 prototype, constructor); | |
466 } | |
467 { | |
468 const WrapperTypeInfo* type = &V8Document::wrapperTypeInfo; | |
469 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
470 v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str) | |
471 .ToLocalChecked() | |
472 .As<v8::Object>(); | |
473 V8Document::InstallRuntimeEnabledFeatures( | |
474 isolate, world, document_wrapper, prototype, constructor); | |
475 } | |
476 { | |
477 const WrapperTypeInfo* type = &V8HTMLDocument::wrapperTypeInfo; | |
478 v8::Local<v8::Function> constructor = data->ConstructorForType(type); | |
479 v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str) | |
480 .ToLocalChecked() | |
481 .As<v8::Object>(); | |
482 V8HTMLDocument::InstallRuntimeEnabledFeatures( | |
483 isolate, world, document_wrapper, prototype, constructor); | |
484 } | |
485 } | |
486 } | |
487 | |
488 void V8SnapshotUtil::SetReferenceTable(intptr_t* table) { | |
489 DCHECK(!g_snapshot_reference_table); | |
490 g_snapshot_reference_table = table; | |
491 } | |
492 | |
493 intptr_t* V8SnapshotUtil::GetReferenceTable() { | |
494 DCHECK(g_snapshot_reference_table); | |
495 return g_snapshot_reference_table; | |
496 } | |
497 | |
498 } // namespace blink | |
OLD | NEW |