Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(563)

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp

Issue 2003033004: Split custom element script use and move it into bindings (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address feedback. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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/ScriptCustomElementDefinition.h"
6
7 #include "bindings/core/v8/ScriptState.h"
8 #include "bindings/core/v8/V8Binding.h"
9 #include "bindings/core/v8/V8CustomElementsRegistry.h"
10 #include "bindings/core/v8/V8HiddenValue.h"
11 #include "wtf/Allocator.h"
12
13 namespace blink {
14
15 // Retrieves the custom elements constructor -> name map, creating it
16 // if necessary. The same map is used to keep prototypes alive.
17 static v8::Local<v8::Map> ensureCustomElementsRegistryMap(
18 ScriptState* scriptState,
19 CustomElementsRegistry* registry)
20 {
21 CHECK(scriptState->world().isMainWorld());
22 v8::Local<v8::String> name = V8HiddenValue::customElementsRegistryMap(
23 scriptState->isolate());
24 v8::Local<v8::Object> wrapper =
25 toV8(registry, scriptState).As<v8::Object>();
26 v8::Local<v8::Value> map =
27 V8HiddenValue::getHiddenValue(scriptState, wrapper, name);
28 if (map.IsEmpty()) {
29 map = v8::Map::New(scriptState->isolate());
30 V8HiddenValue::setHiddenValue(scriptState, wrapper, name, map);
31 }
32 return map.As<v8::Map>();
33 }
34
35 ScriptCustomElementDefinition* ScriptCustomElementDefinition::forConstructor(
36 ScriptState* scriptState,
37 CustomElementsRegistry* registry,
38 const v8::Local<v8::Value>& constructor)
39 {
40 v8::Local<v8::Map> map =
41 ensureCustomElementsRegistryMap(scriptState, registry);
42 v8::Local<v8::Value> nameValue = v8CallOrCrash(
43 map->Get(scriptState->context(), constructor));
44 if (!nameValue->IsString())
45 return nullptr;
46 AtomicString name = toCoreAtomicString(nameValue.As<v8::String>());
47
48 // This downcast is safe because only
49 // ScriptCustomElementDefinitions have a name associated with a V8
50 // constructor in the map; see
51 // ScriptCustomElementDefinition::create. This relies on three
52 // things:
53 //
54 // 1. Only ScriptCustomElementDefinition adds entries to the map.
55 // Audit the use of V8HiddenValue/hidden values in general and
56 // how the map is handled--it should never be leaked to script.
57 //
58 // 2. CustomElementsRegistry does not overwrite definitions with a
59 // given name--see the CHECK in CustomElementsRegistry::define
60 // --and adds ScriptCustomElementDefinitions to the map without
61 // fail.
62 //
63 // 3. The relationship between the CustomElementsRegistry and its
64 // map is never mixed up; this is guaranteed by the bindings
65 // system which provides a stable wrapper, and the map hangs
66 // off the wrapper.
67 //
68 // At a meta-level, this downcast is safe because there is
69 // currently only one implementation of CustomElementDefinition in
70 // product code and that is ScriptCustomElementDefinition. But
71 // that may change in the future.
72 CustomElementDefinition* definition = registry->definitionForName(name);
73 CHECK(definition);
74 return static_cast<ScriptCustomElementDefinition*>(definition);
75 }
76
77 ScriptCustomElementDefinition* ScriptCustomElementDefinition::create(
78 ScriptState* scriptState,
79 CustomElementsRegistry* registry,
80 const CustomElementDescriptor& descriptor,
81 const v8::Local<v8::Object>& constructor,
82 const v8::Local<v8::Object>& prototype)
83 {
84 ScriptCustomElementDefinition* definition =
85 new ScriptCustomElementDefinition(
86 scriptState,
87 descriptor,
88 constructor,
89 prototype);
90
91 // Add a constructor -> name mapping to the registry.
92 v8::Local<v8::Value> nameValue =
93 v8String(scriptState->isolate(), descriptor.name());
94 v8::Local<v8::Map> map =
95 ensureCustomElementsRegistryMap(scriptState, registry);
96 v8CallOrCrash(map->Set(scriptState->context(), constructor, nameValue));
97 // We add the prototype here to keep it alive; we make it a value
98 // not a key so authors cannot return another constructor as a
99 // prototype to overwrite a constructor in this map. We use the
100 // name because it is unique per-registry.
101 v8CallOrCrash(map->Set(scriptState->context(), nameValue, prototype));
102
103 return definition;
104 }
105
106 ScriptCustomElementDefinition::ScriptCustomElementDefinition(
107 ScriptState* scriptState,
108 const CustomElementDescriptor& descriptor,
109 const v8::Local<v8::Object>& constructor,
110 const v8::Local<v8::Object>& prototype)
111 : CustomElementDefinition(descriptor)
112 , m_constructor(scriptState->isolate(), constructor)
113 , m_prototype(scriptState->isolate(), prototype)
114 {
115 // These objects are kept alive by references from the
116 // CustomElementsRegistry wrapper set up by
117 // ScriptCustomElementDefinition::create.
118 m_constructor.setPhantom();
119 m_prototype.setPhantom();
120 }
121
122 v8::Local<v8::Object> ScriptCustomElementDefinition::constructor(
123 ScriptState* scriptState) const
124 {
125 DCHECK(!m_constructor.isEmpty());
126 return m_constructor.newLocal(scriptState->isolate());
127 }
128
129 v8::Local<v8::Object> ScriptCustomElementDefinition::prototype(
130 ScriptState* scriptState) const
131 {
132 DCHECK(!m_prototype.isEmpty());
133 return m_prototype.newLocal(scriptState->isolate());
134 }
135
136 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698