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

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: Remove scope switching. 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 if (!scriptState->contextIsValid())
haraken 2016/05/28 08:29:48 Nit: I'd remove this check. We normally don't che
41 return nullptr;
42 v8::Local<v8::Map> map =
43 ensureCustomElementsRegistryMap(scriptState, registry);
44 v8::Local<v8::Value> nameValue = v8CallOrCrash(
45 map->Get(scriptState->context(), constructor));
46 if (!nameValue->IsString())
47 return nullptr;
48 AtomicString name = toCoreAtomicString(nameValue.As<v8::String>());
49
50 // This downcast is safe because only
51 // ScriptCustomElementDefinitions have a name associated with a V8
52 // constructor in the map; see
53 // ScriptCustomElementDefinition::create. This relies on three
54 // things:
55 //
56 // 1. Only ScriptCustomElementDefinition adds entries to the map.
57 // Audit the use of V8HiddenValue/hidden values in general and
58 // how the map is handled--it should never be leaked to script.
59 //
60 // 2. CustomElementsRegistry does not overwrite definitions with a
61 // given name--see the CHECK in CustomElementsRegistry::define
62 // --and adds ScriptCustomElementDefinitions to the map without
63 // fail.
64 //
65 // 3. The relationship between the CustomElementsRegistry and its
66 // map is never mixed up; this is guaranteed by the bindings
67 // system which provides a stable wrapper, and the map hangs
68 // off the wrapper.
69 //
70 // At a meta-level, this downcast is safe because there is
71 // currently only one implementation of CustomElementDefinition in
72 // product code and that is ScriptCustomElementDefinition. But
73 // that may change in the future.
74 CustomElementDefinition* definition = registry->definitionForName(name);
75 CHECK(definition);
76 return static_cast<ScriptCustomElementDefinition*>(definition);
77 }
78
79 ScriptCustomElementDefinition* ScriptCustomElementDefinition::create(
80 ScriptState* scriptState,
81 CustomElementsRegistry* registry,
82 const CustomElementDescriptor& descriptor,
83 const v8::Local<v8::Object>& constructor,
84 const v8::Local<v8::Object>& prototype)
85 {
86 ScriptCustomElementDefinition* definition =
87 new ScriptCustomElementDefinition(
88 scriptState,
89 descriptor,
90 constructor,
91 prototype);
92
93 // Add a constructor -> name mapping to the registry.
94 v8::Local<v8::Value> nameValue =
95 v8String(scriptState->isolate(), descriptor.name());
96 v8::Local<v8::Map> map =
97 ensureCustomElementsRegistryMap(scriptState, registry);
98 v8CallOrCrash(map->Set(scriptState->context(), constructor, nameValue));
99 // We add the prototype here to keep it alive; we make it a value
100 // not a key so authors cannot return another constructor as a
101 // prototype to overwrite a constructor in this map. We use the
102 // name because it is unique per-registry.
103 v8CallOrCrash(map->Set(scriptState->context(), nameValue, prototype));
104
105 return definition;
106 }
107
108 ScriptCustomElementDefinition::ScriptCustomElementDefinition(
109 ScriptState* scriptState,
110 const CustomElementDescriptor& descriptor,
111 const v8::Local<v8::Object>& constructor,
112 const v8::Local<v8::Object>& prototype)
113 : CustomElementDefinition(descriptor)
114 , m_constructor(scriptState->isolate(), constructor)
115 , m_prototype(scriptState->isolate(), prototype)
116 {
117 // These objects are kept alive by references from the
118 // CustomElementsRegistry wrapper set up by
119 // ScriptCustomElementDefinition::create.
120 m_constructor.setPhantom();
121 m_prototype.setPhantom();
122 }
123
124 v8::Local<v8::Object> ScriptCustomElementDefinition::constructor(
125 ScriptState* scriptState) const
126 {
127 DCHECK(!m_constructor.isEmpty());
128 return m_constructor.newLocal(scriptState->isolate());
129 }
130
131 v8::Local<v8::Object> ScriptCustomElementDefinition::prototype(
132 ScriptState* scriptState) const
133 {
134 DCHECK(!m_prototype.isEmpty());
135 return m_prototype.newLocal(scriptState->isolate());
136 }
137
138 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698