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 <array> | |
8 #include <cstring> | |
9 | |
10 #include "bindings/core/v8/GeneratedCodeHelper.h" | |
11 #include "bindings/core/v8/V8Document.h" | |
12 #include "bindings/core/v8/V8EventTarget.h" | |
13 #include "bindings/core/v8/V8HTMLDocument.h" | |
14 #include "bindings/core/v8/V8Initializer.h" | |
15 #include "bindings/core/v8/V8Node.h" | |
16 #include "bindings/core/v8/V8Window.h" | |
17 #include "platform/bindings/DOMWrapperWorld.h" | |
18 #include "platform/bindings/V8ObjectConstructor.h" | |
19 #include "platform/bindings/V8PerIsolateData.h" | |
20 #include "platform/bindings/V8PrivateProperty.h" | |
21 #include "v8/include/v8.h" | |
22 | |
23 namespace blink { | |
24 | |
25 namespace { | |
26 | |
27 intptr_t* g_snapshot_reference_table = nullptr; | |
28 | |
29 // TODO(peria): This method is almost a copy of | |
30 // V8PerContext::ConstructorForTypeSlowCase(), so merge with it. | |
31 v8::Local<v8::Function> ConstructPlainType(v8::Isolate* isolate, | |
32 const DOMWrapperWorld& world, | |
33 v8::Local<v8::Context> context, | |
34 const WrapperTypeInfo* type) { | |
35 v8::Context::Scope scope(context); | |
36 // We shouldn't reach this point for the types that are implemented in v8 such | |
37 // as typed arrays and hence don't have domTemplateFunction. | |
38 DCHECK(type->dom_template_function); | |
39 v8::Local<v8::FunctionTemplate> interface_template = | |
40 type->domTemplate(isolate, world); | |
41 // Getting the function might fail if we're running out of stack or memory. | |
42 v8::Local<v8::Function> interface_object = | |
43 interface_template->GetFunction(context).ToLocalChecked(); | |
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 interface_object->Get(context, V8AtomicString(isolate, "prototype")) | |
54 .ToLocalChecked(); | |
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 V8ObjectConstructor::NewInstance(isolate, interface_object) | |
84 .ToLocalChecked(); | |
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 constexpr size_t kSnapshotWrapperSize = WTF_ARRAY_LENGTH(kSnapshotWrapperTypes); | |
104 | |
105 enum class InternalFieldType : uint8_t { | |
106 kNone, | |
107 kNodeType, | |
108 kDocumentType, | |
109 kHTMLDocumentType, | |
110 kHTMLDocumentObject, | |
111 }; | |
112 | |
113 const WrapperTypeInfo* FieldTypeToWrapperTypeInfo(InternalFieldType type) { | |
114 switch (type) { | |
115 case InternalFieldType::kNone: | |
116 NOTREACHED(); | |
117 break; | |
118 case InternalFieldType::kNodeType: | |
119 return &V8Node::wrapperTypeInfo; | |
120 case InternalFieldType::kDocumentType: | |
121 return &V8Document::wrapperTypeInfo; | |
122 case InternalFieldType::kHTMLDocumentType: | |
123 return &V8HTMLDocument::wrapperTypeInfo; | |
124 case InternalFieldType::kHTMLDocumentObject: | |
125 return &V8HTMLDocument::wrapperTypeInfo; | |
126 } | |
127 NOTREACHED(); | |
128 return nullptr; | |
129 } | |
130 | |
131 struct DataForDeserializer { | |
132 STACK_ALLOCATED(); | |
133 Member<Document> document; | |
134 }; | |
135 | |
136 int CountExternalReferenceEntries() { | |
137 if (!g_snapshot_reference_table) | |
138 return 0; | |
139 | |
140 int count = 0; | |
141 for (intptr_t* p = g_snapshot_reference_table; *p; ++p) | |
142 ++count; | |
143 return count; | |
144 } | |
145 | |
146 } // namespace | |
147 | |
148 v8::Local<v8::Context> V8SnapshotUtil::CreateContext( | |
149 v8::Isolate* isolate, | |
150 const DOMWrapperWorld& world, | |
151 v8::ExtensionConfiguration* extension_configuration, | |
152 v8::Local<v8::Object> global_proxy, | |
153 Document* document) { | |
154 if (!CanCreateContextFromSnapshot(isolate, world, document)) { | |
155 return v8::Local<v8::Context>(); | |
156 } | |
157 | |
158 const int index = GetSnapshotIndexForWorld(world); | |
159 DataForDeserializer data{document}; | |
160 v8::DeserializeInternalFieldsCallback callback = | |
161 v8::DeserializeInternalFieldsCallback(&DeserializeInternalField, &data); | |
162 v8::Local<v8::Context> context = | |
163 v8::Context::FromSnapshot(isolate, index, callback, | |
164 extension_configuration, global_proxy) | |
165 .ToLocalChecked(); | |
166 CHECK(!context.IsEmpty()); | |
Yuki
2017/06/27 12:43:47
This CHECK is meaningless after ToLocalChecked().
peria
2017/06/28 03:02:43
Done.
| |
167 DLOG(INFO) << "A context is created from snapshot for " | |
168 << (world.IsMainWorld() ? "" : "non-") << "main world"; | |
169 | |
170 return context; | |
171 } | |
172 | |
173 void V8SnapshotUtil::SetupContext(v8::Local<v8::Context> context, | |
174 Document* document) { | |
175 ScriptState* script_state = ScriptState::From(context); | |
176 v8::Isolate* isolate = script_state->GetIsolate(); | |
177 const DOMWrapperWorld& world = script_state->World(); | |
178 if (!CanCreateContextFromSnapshot(isolate, world, document)) { | |
179 return; | |
180 } | |
181 | |
182 v8::Local<v8::String> prototype_str = V8AtomicString(isolate, "prototype"); | |
183 V8PerContextData* data = script_state->PerContextData(); | |
184 | |
185 v8::Local<v8::Object> global_proxy = context->Global(); | |
186 v8::Local<v8::Object> window_wrapper = | |
187 global_proxy->GetPrototype().As<v8::Object>(); | |
188 { | |
189 const WrapperTypeInfo* type = &V8EventTarget::wrapperTypeInfo; | |
190 v8::Local<v8::Function> interface = data->ConstructorForType(type); | |
191 v8::Local<v8::Object> prototype = interface->Get(context, prototype_str) | |
192 .ToLocalChecked() | |
193 .As<v8::Object>(); | |
194 V8EventTarget::InstallRuntimeEnabledFeatures(isolate, world, window_wrapper, | |
Yuki
2017/06/27 12:43:47
I'm confused again. Exactly what InstallRuntimeEn
peria
2017/06/28 03:02:43
Ah, I think your understanding is correct.
No need
| |
195 prototype, interface); | |
196 } | |
197 { | |
198 const WrapperTypeInfo* type = &V8Window::wrapperTypeInfo; | |
199 v8::Local<v8::Function> interface = data->ConstructorForType(type); | |
200 v8::Local<v8::Object> prototype = interface->Get(context, prototype_str) | |
201 .ToLocalChecked() | |
202 .As<v8::Object>(); | |
203 V8Window::install_runtime_enabled_features_function_( | |
204 isolate, world, window_wrapper, prototype, interface); | |
205 } | |
206 | |
207 if (world.IsMainWorld()) { | |
Yuki
2017/06/27 12:43:49
nit: Can we do an early-exit?
peria
2017/06/28 03:02:43
Done.
| |
208 CHECK(document); | |
209 DCHECK(document->IsHTMLDocument()); | |
210 CHECK(document->ContainsWrapper()); | |
211 v8::Local<v8::Object> document_wrapper = | |
212 document->MainWorldWrapper(isolate); | |
Yuki
2017/06/27 12:43:47
Is this the only reason that V8SnapshotUtil needs
peria
2017/06/28 03:02:43
Done.
| |
213 | |
214 { | |
215 // Prototype object and interface object of EventTarget were set up with | |
216 // Window wrapper. | |
217 V8EventTarget::InstallRuntimeEnabledFeatures( | |
218 isolate, world, document_wrapper, v8::Local<v8::Object>(), | |
219 v8::Local<v8::Function>()); | |
220 } | |
221 { | |
222 const WrapperTypeInfo* type = &V8Node::wrapperTypeInfo; | |
223 v8::Local<v8::Function> interface = data->ConstructorForType(type); | |
224 v8::Local<v8::Object> prototype = interface->Get(context, prototype_str) | |
225 .ToLocalChecked() | |
226 .As<v8::Object>(); | |
227 V8Node::InstallRuntimeEnabledFeatures(isolate, world, document_wrapper, | |
228 prototype, interface); | |
229 } | |
230 { | |
231 const WrapperTypeInfo* type = &V8Document::wrapperTypeInfo; | |
232 v8::Local<v8::Function> interface = data->ConstructorForType(type); | |
233 v8::Local<v8::Object> prototype = interface->Get(context, prototype_str) | |
234 .ToLocalChecked() | |
235 .As<v8::Object>(); | |
236 V8Document::InstallRuntimeEnabledFeatures( | |
237 isolate, world, document_wrapper, prototype, interface); | |
238 } | |
239 { | |
240 const WrapperTypeInfo* type = &V8HTMLDocument::wrapperTypeInfo; | |
241 v8::Local<v8::Function> interface = data->ConstructorForType(type); | |
242 v8::Local<v8::Object> prototype = interface->Get(context, prototype_str) | |
243 .ToLocalChecked() | |
244 .As<v8::Object>(); | |
245 V8HTMLDocument::InstallRuntimeEnabledFeatures( | |
246 isolate, world, document_wrapper, prototype, interface); | |
247 } | |
248 } | |
249 } | |
250 | |
251 void V8SnapshotUtil::EnsureInterfaceTemplates(v8::Isolate* isolate) { | |
252 if (V8PerIsolateData::From(isolate)->GetV8ContextMode() != | |
253 V8PerIsolateData::V8ContextMode::kUseSnapshot) { | |
254 return; | |
255 } | |
256 | |
257 EnsureInterfaceTemplatesForWorld(isolate, DOMWrapperWorld::MainWorld()); | |
258 EnsureInterfaceTemplatesForWorld( | |
259 isolate, | |
260 *DOMWrapperWorld::EnsureIsolatedWorld(isolate, kWorldIdForNonMainWorld)); | |
261 } | |
262 | |
263 void V8SnapshotUtil::SetReferenceTable(intptr_t* table) { | |
264 DCHECK(!g_snapshot_reference_table); | |
265 g_snapshot_reference_table = table; | |
266 } | |
267 | |
268 intptr_t* V8SnapshotUtil::GetReferenceTable() { | |
269 DCHECK(g_snapshot_reference_table); | |
270 return g_snapshot_reference_table; | |
271 } | |
272 | |
273 v8::StartupData V8SnapshotUtil::TakeSnapshot() { | |
274 DCHECK_EQ(V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate()) | |
275 ->GetV8ContextMode(), | |
276 V8PerIsolateData::V8ContextMode::kTakeSnapshot); | |
277 | |
278 v8::SnapshotCreator* creator = | |
279 V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate()) | |
280 ->GetSnapshotCreator(); | |
281 v8::Isolate* isolate = creator->GetIsolate(); | |
282 CHECK_EQ(isolate, v8::Isolate::GetCurrent()); | |
283 | |
284 VLOG(1) << "External reference table has " << CountExternalReferenceEntries() | |
285 << " entries."; | |
286 | |
287 // Disable all runtime enabled featuers | |
288 RuntimeEnabledFeatures::SetStableFeaturesEnabled(false); | |
289 RuntimeEnabledFeatures::SetExperimentalFeaturesEnabled(false); | |
290 RuntimeEnabledFeatures::SetTestFeaturesEnabled(false); | |
291 | |
292 { | |
293 v8::HandleScope handleScope(isolate); | |
294 creator->SetDefaultContext(v8::Context::New(isolate)); | |
295 | |
296 TakeSnapshotForWorld(creator, DOMWrapperWorld::MainWorld()); | |
297 // For non main worlds, we can use any type to create a context. | |
298 TakeSnapshotForWorld(creator, *DOMWrapperWorld::EnsureIsolatedWorld( | |
299 isolate, kWorldIdForNonMainWorld)); | |
300 } | |
301 | |
302 // Snapshot is taken on the main thread, but it can be used on other threads. | |
303 // So we remove a message handler for the main thread. | |
304 isolate->RemoveMessageListeners(V8Initializer::MessageHandlerInMainThread); | |
305 | |
306 return creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); | |
307 } | |
308 | |
309 v8::StartupData V8SnapshotUtil::SerializeInternalField( | |
310 v8::Local<v8::Object> object, | |
311 int index, | |
312 void*) { | |
313 InternalFieldType field_type = InternalFieldType::kNone; | |
314 const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(object); | |
315 if (kV8DOMWrapperObjectIndex == index) { | |
316 if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) { | |
317 field_type = InternalFieldType::kHTMLDocumentObject; | |
318 } | |
319 } else if (kV8DOMWrapperTypeIndex == index) { | |
320 if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) { | |
321 field_type = InternalFieldType::kHTMLDocumentType; | |
322 } else if (blink::V8Document::wrapperTypeInfo.Equals(wrapper_type)) { | |
323 field_type = InternalFieldType::kDocumentType; | |
324 } else if (blink::V8Node::wrapperTypeInfo.Equals(wrapper_type)) { | |
325 field_type = InternalFieldType::kNodeType; | |
326 } | |
327 } | |
328 CHECK_NE(field_type, InternalFieldType::kNone); | |
329 | |
330 int size = sizeof(InternalFieldType); | |
331 char* data = new char[size]; | |
332 std::memcpy(data, &field_type, size); | |
333 | |
334 return {data, size}; | |
335 } | |
336 | |
337 void V8SnapshotUtil::DeserializeInternalField(v8::Local<v8::Object> object, | |
338 int index, | |
339 v8::StartupData payload, | |
340 void* ptr) { | |
341 // DeserializeInternalField() expects to be called in the main world | |
342 // with |document| being HTMLDocument. | |
343 CHECK_EQ(payload.raw_size, static_cast<int>(sizeof(InternalFieldType))); | |
344 InternalFieldType type = | |
345 *reinterpret_cast<const InternalFieldType*>(payload.data); | |
346 | |
347 const WrapperTypeInfo* wrapper_type_info = FieldTypeToWrapperTypeInfo(type); | |
348 switch (type) { | |
349 case InternalFieldType::kNodeType: | |
350 case InternalFieldType::kDocumentType: | |
351 case InternalFieldType::kHTMLDocumentType: { | |
352 CHECK_EQ(index, kV8DOMWrapperTypeIndex); | |
353 object->SetAlignedPointerInInternalField( | |
354 index, const_cast<WrapperTypeInfo*>(wrapper_type_info)); | |
355 return; | |
356 } | |
357 case InternalFieldType::kHTMLDocumentObject: { | |
358 LOG(INFO) << "wrapper"; | |
359 CHECK_EQ(index, kV8DOMWrapperObjectIndex); | |
360 LOG(INFO) << "setting document wrapper"; | |
361 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | |
362 DataForDeserializer* data = static_cast<DataForDeserializer*>(ptr); | |
363 ScriptWrappable* document = data->document; | |
364 DCHECK(document); | |
365 | |
366 // Make reference from wrapper to document | |
367 object->SetAlignedPointerInInternalField(index, document); | |
368 // Make reference from document to wrapper | |
369 CHECK(document->SetWrapper(isolate, wrapper_type_info, object)); | |
370 WrapperTypeInfo::WrapperCreated(); | |
371 return; | |
372 } | |
373 case InternalFieldType::kNone: | |
374 NOTREACHED(); | |
375 return; | |
376 } | |
377 | |
378 NOTREACHED(); | |
379 } | |
380 | |
381 bool V8SnapshotUtil::CanCreateContextFromSnapshot(v8::Isolate* isolate, | |
382 const DOMWrapperWorld& world, | |
383 Document* document) { | |
Yuki
2017/06/27 12:43:47
nit: Can we add DCHECK(document)?
If document ==
peria
2017/06/28 03:02:43
Done.
| |
384 if (V8PerIsolateData::From(isolate)->GetV8ContextMode() != | |
385 V8PerIsolateData::V8ContextMode::kUseSnapshot) { | |
386 return false; | |
387 } | |
388 // In case we create a context for the main world from snapshot, we also need | |
389 // a HTMLDocument wrapper. | |
390 if (world.IsMainWorld() && !(document && document->IsHTMLDocument())) { | |
Yuki
2017/06/27 12:43:47
nit: A→B is defined as ¬A∨B, hence (!A || B) is on
peria
2017/06/28 03:02:43
Done.
| |
391 return false; | |
392 } | |
393 return true; | |
394 } | |
395 | |
396 void V8SnapshotUtil::EnsureInterfaceTemplatesForWorld( | |
397 v8::Isolate* isolate, | |
398 const DOMWrapperWorld& world) { | |
399 V8PerIsolateData* data = V8PerIsolateData::From(isolate); | |
400 for (const WrapperTypeInfo* wrapper_type_info : kSnapshotWrapperTypes) { | |
401 v8::Local<v8::FunctionTemplate> interface = | |
402 InterfaceTemplateFromSnapshot(isolate, world, wrapper_type_info); | |
403 CHECK(!interface.IsEmpty()); | |
404 data->SetInterfaceTemplate(world, wrapper_type_info, interface); | |
405 } | |
406 } | |
407 | |
408 v8::Local<v8::FunctionTemplate> V8SnapshotUtil::InterfaceTemplateFromSnapshot( | |
409 v8::Isolate* isolate, | |
410 const DOMWrapperWorld& world, | |
411 const WrapperTypeInfo* wrapper_type_info) { | |
412 static const InstallRuntimeEnabledFeaturesOnTemplateFunction kInstallers[] = { | |
Yuki
2017/06/27 12:43:49
Maybe my comment was unclear. I was recommending
peria
2017/06/28 03:02:43
Done.
| |
413 V8Window::install_runtime_enabled_features_on_template_function_, | |
414 V8HTMLDocument::InstallRuntimeEnabledFeaturesOnTemplate, | |
415 V8EventTarget::InstallRuntimeEnabledFeaturesOnTemplate, | |
416 V8Node::InstallRuntimeEnabledFeaturesOnTemplate, | |
417 V8Document::InstallRuntimeEnabledFeaturesOnTemplate, | |
418 }; | |
419 | |
420 const int index_offset = world.IsMainWorld() ? 0 : kSnapshotWrapperSize; | |
421 | |
422 for (size_t i = 0; i < kSnapshotWrapperSize; ++i) { | |
423 if (kSnapshotWrapperTypes[i]->Equals(wrapper_type_info)) { | |
424 v8::Local<v8::FunctionTemplate> interface_template = | |
425 v8::FunctionTemplate::FromSnapshot(isolate, index_offset + i) | |
426 .ToLocalChecked(); | |
427 kInstallers[i](isolate, world, interface_template); | |
Yuki
2017/06/27 12:43:49
Just a comment for future work, it's not good to h
peria
2017/06/28 03:02:43
Acknowledged.
| |
428 return interface_template; | |
429 } | |
430 } | |
431 | |
432 NOTREACHED(); | |
433 return v8::Local<v8::FunctionTemplate>(); | |
434 } | |
435 | |
436 void V8SnapshotUtil::TakeSnapshotForWorld(v8::SnapshotCreator* creator, | |
437 const DOMWrapperWorld& world) { | |
438 v8::Isolate* isolate = creator->GetIsolate(); | |
439 CHECK_EQ(isolate, v8::Isolate::GetCurrent()); | |
440 | |
441 // Function templates | |
442 v8::HandleScope handleScope(isolate); | |
443 std::array<v8::Local<v8::FunctionTemplate>, kSnapshotWrapperSize> | |
444 interface_templates; | |
445 v8::Local<v8::FunctionTemplate> window_template; | |
446 for (size_t i = 0; i < kSnapshotWrapperSize; ++i) { | |
447 const WrapperTypeInfo* wrapper_type_info = kSnapshotWrapperTypes[i]; | |
448 v8::Local<v8::FunctionTemplate> interface_template = | |
449 wrapper_type_info->domTemplate(isolate, world); | |
450 CHECK(!interface_template.IsEmpty()); | |
451 interface_templates[i] = interface_template; | |
452 if (V8Window::wrapperTypeInfo.Equals(wrapper_type_info)) { | |
453 window_template = interface_template; | |
454 } | |
455 } | |
456 CHECK(!window_template.IsEmpty()); | |
457 | |
458 v8::Local<v8::ObjectTemplate> window_instance_template = | |
459 window_template->InstanceTemplate(); | |
460 CHECK(!window_instance_template.IsEmpty()); | |
461 | |
462 v8::Local<v8::Context> context; | |
463 { | |
464 V8PerIsolateData::UseCounterDisabledScope use_counter_disabled( | |
465 V8PerIsolateData::From(isolate)); | |
466 context = v8::Context::New(isolate, nullptr, window_instance_template); | |
467 } | |
468 CHECK(!context.IsEmpty()); | |
469 | |
470 if (world.IsMainWorld()) { | |
471 v8::Context::Scope scope(context); | |
472 v8::Local<v8::Object> document_wrapper = CreatePlainWrapper( | |
473 isolate, world, context, &V8HTMLDocument::wrapperTypeInfo); | |
474 int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex}; | |
475 void* values[] = {nullptr, const_cast<WrapperTypeInfo*>( | |
476 &V8HTMLDocument::wrapperTypeInfo)}; | |
477 document_wrapper->SetAlignedPointerInInternalFields( | |
478 WTF_ARRAY_LENGTH(indices), indices, values); | |
479 | |
480 // Set the cached accessor for window.document. | |
481 CHECK(V8PrivateProperty::GetWindowDocumentCachedAccessor(isolate).Set( | |
482 context->Global(), document_wrapper)); | |
483 } | |
484 | |
485 for (auto& interface_template : interface_templates) { | |
486 creator->AddTemplate(interface_template); | |
487 } | |
488 creator->AddContext(context, SerializeInternalField); | |
489 | |
490 V8PerIsolateData::From(isolate)->ClearPersistentsForV8Snapshot(); | |
491 } | |
492 | |
493 } // namespace blink | |
OLD | NEW |