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

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

Issue 2828643002: Make customElements.define faster
Patch Set: Remove some unneeded casts. Created 3 years, 7 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "bindings/core/v8/ScriptCustomElementDefinitionBuilder.h" 5 #include "bindings/core/v8/ScriptCustomElementDefinitionBuilder.h"
6 6
7 #include "bindings/core/v8/DOMWrapperWorld.h" 7 #include <utility>
8 #include "bindings/core/v8/ExceptionState.h" 8 #include "bindings/core/v8/ExceptionState.h"
9 #include "bindings/core/v8/IDLTypes.h" 9 #include "bindings/core/v8/IDLTypes.h"
10 #include "bindings/core/v8/NativeValueTraitsImpl.h" 10 #include "bindings/core/v8/NativeValueTraitsImpl.h"
11 #include "bindings/core/v8/ScriptCustomElementDefinition.h" 11 #include "bindings/core/v8/ScriptCustomElementDefinition.h"
12 #include "bindings/core/v8/ScriptState.h" 12 #include "bindings/core/v8/ScriptState.h"
13 #include "bindings/core/v8/ScriptValue.h" 13 #include "bindings/core/v8/ScriptValue.h"
14 #include "bindings/core/v8/V8BindingForCore.h" 14 #include "bindings/core/v8/V8BindingForCore.h"
15 #include "bindings/core/v8/V8BindingMacros.h" 15 #include "bindings/core/v8/V8BindingMacros.h"
16 #include "core/dom/ExceptionCode.h" 16 #include "core/dom/ExceptionCode.h"
17 17
18 namespace blink { 18 namespace blink {
19 19
20 ScriptCustomElementDefinitionBuilder*
21 ScriptCustomElementDefinitionBuilder::stack_ = nullptr;
22
23 ScriptCustomElementDefinitionBuilder::ScriptCustomElementDefinitionBuilder( 20 ScriptCustomElementDefinitionBuilder::ScriptCustomElementDefinitionBuilder(
24 ScriptState* script_state, 21 ScriptState* script_state,
25 CustomElementRegistry* registry, 22 CustomElementRegistry* registry,
26 const ScriptValue& constructor, 23 const ScriptValue& constructor,
27 ExceptionState& exception_state) 24 ExceptionState& exception_state)
28 : prev_(stack_), 25 : script_state_(script_state),
29 script_state_(script_state),
30 registry_(registry), 26 registry_(registry),
31 constructor_value_(constructor.V8Value()), 27 constructor_value_(constructor.V8Value()),
32 exception_state_(exception_state) { 28 exception_state_(exception_state) {}
33 stack_ = this;
34 }
35
36 ScriptCustomElementDefinitionBuilder::~ScriptCustomElementDefinitionBuilder() {
37 stack_ = prev_;
38 }
39 29
40 bool ScriptCustomElementDefinitionBuilder::CheckConstructorIntrinsics() { 30 bool ScriptCustomElementDefinitionBuilder::CheckConstructorIntrinsics() {
41 DCHECK(script_state_->World().IsMainWorld()); 31 DCHECK(script_state_->World().IsMainWorld());
42 32
43 // The signature of CustomElementRegistry.define says this is a 33 // The signature of CustomElementRegistry.define says this is a
44 // Function 34 // Function
45 // https://html.spec.whatwg.org/multipage/scripting.html#customelementsregistr y 35 // https://html.spec.whatwg.org/multipage/scripting.html#customelementsregistr y
46 CHECK(constructor_value_->IsFunction()); 36 CHECK(constructor_value_->IsFunction());
47 constructor_ = constructor_value_.As<v8::Object>(); 37 constructor_ = constructor_value_.As<v8::Object>();
48 if (!constructor_->IsConstructor()) { 38 if (!constructor_->IsConstructor()) {
49 exception_state_.ThrowTypeError( 39 exception_state_.ThrowTypeError(
50 "constructor argument is not a constructor"); 40 "constructor argument is not a constructor");
51 return false; 41 return false;
52 } 42 }
53 return true; 43 return true;
54 } 44 }
55 45
56 bool ScriptCustomElementDefinitionBuilder::CheckConstructorNotRegistered() { 46 bool ScriptCustomElementDefinitionBuilder::CheckConstructorNotRegistered() {
57 if (ScriptCustomElementDefinition::ForConstructor(script_state_.Get(), 47 if (!ScriptCustomElementDefinition::ForConstructor(script_state_.Get(),
58 registry_, constructor_)) { 48 registry_, constructor_)) {
59 // Constructor is already registered. 49 return true;
60 exception_state_.ThrowDOMException(
61 kNotSupportedError,
62 "this constructor has already been used with this registry");
63 return false;
64 } 50 }
65 for (auto builder = prev_; builder; builder = builder->prev_) { 51 // Constructor is already registered.
66 CHECK(!builder->constructor_.IsEmpty()); 52 exception_state_.ThrowDOMException(
67 if (registry_ != builder->registry_ || 53 kNotSupportedError,
68 constructor_ != builder->constructor_) { 54 "this constructor has already been used with this registry");
69 continue; 55 return false;
70 }
71 exception_state_.ThrowDOMException(
72 kNotSupportedError,
73 "this constructor is already being defined in this registry");
74 return false;
75 }
76 return true;
77 } 56 }
78 57
79 bool ScriptCustomElementDefinitionBuilder::ValueForName( 58 bool ScriptCustomElementDefinitionBuilder::ValueForName(
59 v8::Isolate* isolate,
60 v8::Local<v8::Context>& context,
61 const v8::TryCatch& try_catch,
80 const v8::Local<v8::Object>& object, 62 const v8::Local<v8::Object>& object,
81 const StringView& name, 63 const StringView& name,
82 v8::Local<v8::Value>& value) const { 64 v8::Local<v8::Value>& value) const {
83 v8::Isolate* isolate = script_state_->GetIsolate();
84 v8::Local<v8::Context> context = script_state_->GetContext();
85 v8::Local<v8::String> name_string = V8AtomicString(isolate, name); 65 v8::Local<v8::String> name_string = V8AtomicString(isolate, name);
86 v8::TryCatch try_catch(isolate);
87 if (!object->Get(context, name_string).ToLocal(&value)) { 66 if (!object->Get(context, name_string).ToLocal(&value)) {
88 exception_state_.RethrowV8Exception(try_catch.Exception()); 67 exception_state_.RethrowV8Exception(try_catch.Exception());
89 return false; 68 return false;
90 } 69 }
91 return true; 70 return script_state_->ContextIsValid();
haraken 2017/04/28 08:49:30 What is this change for?
92 } 71 }
93 72
94 bool ScriptCustomElementDefinitionBuilder::CheckPrototype() { 73 bool ScriptCustomElementDefinitionBuilder::CheckPrototype() {
74 v8::Isolate* isolate = script_state_->GetIsolate();
75 v8::Local<v8::Context> context = script_state_->GetContext();
76 v8::TryCatch try_catch(isolate);
haraken 2017/04/28 08:49:30 Are you intentionally moving the TryCatch scope to
95 v8::Local<v8::Value> prototype_value; 77 v8::Local<v8::Value> prototype_value;
96 if (!ValueForName(constructor_, "prototype", prototype_value)) 78 if (!ValueForName(isolate, context, try_catch, constructor_, "prototype",
79 prototype_value))
97 return false; 80 return false;
98 if (!prototype_value->IsObject()) { 81 if (!prototype_value->IsObject()) {
99 exception_state_.ThrowTypeError("constructor prototype is not an object"); 82 exception_state_.ThrowTypeError("constructor prototype is not an object");
100 return false; 83 return false;
101 } 84 }
102 prototype_ = prototype_value.As<v8::Object>(); 85 prototype_ = prototype_value.As<v8::Object>();
103 // If retrieving the prototype destroyed the context, indicate that 86 // If retrieving the prototype destroyed the context, indicate that
104 // defining the element should not proceed. 87 // defining the element should not proceed.
105 return true; 88 return script_state_->ContextIsValid();
106 } 89 }
107 90
108 bool ScriptCustomElementDefinitionBuilder::CallableForName( 91 bool ScriptCustomElementDefinitionBuilder::CallableForName(
92 v8::Isolate* isolate,
93 v8::Local<v8::Context>& context,
94 const v8::TryCatch& try_catch,
109 const StringView& name, 95 const StringView& name,
110 v8::Local<v8::Function>& callback) const { 96 v8::Local<v8::Function>& callback) const {
111 v8::Local<v8::Value> value; 97 v8::Local<v8::Value> value;
112 if (!ValueForName(prototype_, name, value)) 98 if (!ValueForName(isolate, context, try_catch, prototype_, name, value))
113 return false; 99 return false;
114 // "undefined" means "omitted", so return true. 100 // "undefined" means "omitted" which is valid.
115 if (value->IsUndefined()) 101 if (value->IsUndefined())
116 return true; 102 return true;
117 if (!value->IsFunction()) { 103 if (!value->IsFunction()) {
118 exception_state_.ThrowTypeError(String::Format( 104 exception_state_.ThrowTypeError(String::Format(
119 "\"%s\" is not a callable object", name.ToString().Ascii().data())); 105 "\"%s\" is not a callable object", name.ToString().Ascii().data()));
120 return false; 106 return false;
121 } 107 }
122 callback = value.As<v8::Function>(); 108 callback = value.As<v8::Function>();
123 return true; 109 return true;
124 } 110 }
125 111
126 bool ScriptCustomElementDefinitionBuilder::RetrieveObservedAttributes() { 112 bool ScriptCustomElementDefinitionBuilder::RetrieveObservedAttributes(
113 v8::Isolate* isolate,
114 v8::Local<v8::Context>& context,
115 const v8::TryCatch& try_catch) {
127 v8::Local<v8::Value> observed_attributes_value; 116 v8::Local<v8::Value> observed_attributes_value;
128 if (!ValueForName(constructor_, "observedAttributes", 117 if (!ValueForName(isolate, context, try_catch, constructor_,
129 observed_attributes_value)) 118 "observedAttributes", observed_attributes_value))
130 return false; 119 return false;
131 if (observed_attributes_value->IsUndefined()) 120 if (observed_attributes_value->IsUndefined())
132 return true; 121 return true;
133 Vector<String> list = NativeValueTraits<IDLSequence<IDLString>>::NativeValue( 122 Vector<String> list = NativeValueTraits<IDLSequence<IDLString>>::NativeValue(
134 script_state_->GetIsolate(), observed_attributes_value, exception_state_); 123 isolate, observed_attributes_value, exception_state_);
135 if (exception_state_.HadException()) 124 if (exception_state_.HadException() || !script_state_->ContextIsValid())
136 return false; 125 return false;
137 if (list.IsEmpty()) 126 if (list.IsEmpty())
138 return true; 127 return true;
139 observed_attributes_.ReserveCapacityForSize(list.size()); 128 observed_attributes_.ReserveCapacityForSize(list.size());
140 for (const auto& attribute : list) 129 for (const auto& attribute : list)
141 observed_attributes_.insert(AtomicString(attribute)); 130 observed_attributes_.insert(AtomicString(attribute));
142 return true; 131 return true;
143 } 132 }
144 133
145 bool ScriptCustomElementDefinitionBuilder::RememberOriginalProperties() { 134 bool ScriptCustomElementDefinitionBuilder::RememberOriginalProperties() {
146 // Spec requires to use values of these properties at the point 135 // Spec requires to use values of these properties at the point
147 // CustomElementDefinition is built, even if JS changes them afterwards. 136 // CustomElementDefinition is built, even if JS changes them afterwards.
148 return CallableForName("connectedCallback", connected_callback_) && 137 v8::Isolate* isolate = script_state_->GetIsolate();
149 CallableForName("disconnectedCallback", disconnected_callback_) && 138 v8::Local<v8::Context> context = script_state_->GetContext();
150 CallableForName("adoptedCallback", adopted_callback_) && 139 v8::TryCatch try_catch(isolate);
151 CallableForName("attributeChangedCallback", 140 return CallableForName(isolate, context, try_catch, "connectedCallback",
141 connected_callback_) &&
142 CallableForName(isolate, context, try_catch, "disconnectedCallback",
143 disconnected_callback_) &&
144 CallableForName(isolate, context, try_catch, "adoptedCallback",
145 adopted_callback_) &&
146 CallableForName(isolate, context, try_catch,
147 "attributeChangedCallback",
152 attribute_changed_callback_) && 148 attribute_changed_callback_) &&
153 (attribute_changed_callback_.IsEmpty() || 149 (attribute_changed_callback_.IsEmpty() ||
154 RetrieveObservedAttributes()); 150 RetrieveObservedAttributes(isolate, context, try_catch));
155 } 151 }
156 152
157 CustomElementDefinition* ScriptCustomElementDefinitionBuilder::Build( 153 CustomElementDefinition* ScriptCustomElementDefinitionBuilder::Build(
158 const CustomElementDescriptor& descriptor) { 154 const CustomElementDescriptor& descriptor,
155 CustomElementDefinition::Id id) {
159 return ScriptCustomElementDefinition::Create( 156 return ScriptCustomElementDefinition::Create(
160 script_state_.Get(), registry_, descriptor, constructor_, 157 script_state_.Get(), registry_, descriptor, id, constructor_,
161 connected_callback_, disconnected_callback_, adopted_callback_, 158 connected_callback_, disconnected_callback_, adopted_callback_,
162 attribute_changed_callback_, observed_attributes_); 159 attribute_changed_callback_, std::move(observed_attributes_));
163 } 160 }
164 161
165 } // namespace blink 162 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698