OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "bindings/core/v8/V8PerContextData.h" | |
32 | |
33 #include <stdlib.h> | |
34 #include <memory> | |
35 #include "bindings/core/v8/ConditionalFeatures.h" | |
36 #include "bindings/core/v8/ScriptState.h" | |
37 #include "bindings/core/v8/V8Binding.h" | |
38 #include "bindings/core/v8/V8ObjectConstructor.h" | |
39 #include "platform/InstanceCounters.h" | |
40 #include "platform/wtf/PtrUtil.h" | |
41 #include "platform/wtf/StringExtras.h" | |
42 | |
43 namespace blink { | |
44 | |
45 V8PerContextData::V8PerContextData(v8::Local<v8::Context> context) | |
46 : isolate_(context->GetIsolate()), | |
47 wrapper_boilerplates_(isolate_), | |
48 constructor_map_(isolate_), | |
49 context_holder_(WTF::MakeUnique<gin::ContextHolder>(isolate_)), | |
50 context_(isolate_, context), | |
51 activity_logger_(nullptr) { | |
52 context_holder_->SetContext(context); | |
53 | |
54 v8::Context::Scope context_scope(context); | |
55 DCHECK(error_prototype_.IsEmpty()); | |
56 v8::Local<v8::Value> object_value = | |
57 context->Global() | |
58 ->Get(context, V8AtomicString(isolate_, "Error")) | |
59 .ToLocalChecked(); | |
60 v8::Local<v8::Value> prototype_value = | |
61 object_value.As<v8::Object>() | |
62 ->Get(context, V8AtomicString(isolate_, "prototype")) | |
63 .ToLocalChecked(); | |
64 error_prototype_.Set(isolate_, prototype_value); | |
65 | |
66 if (IsMainThread()) | |
67 InstanceCounters::IncrementCounter( | |
68 InstanceCounters::kV8PerContextDataCounter); | |
69 } | |
70 | |
71 V8PerContextData::~V8PerContextData() { | |
72 if (IsMainThread()) | |
73 InstanceCounters::DecrementCounter( | |
74 InstanceCounters::kV8PerContextDataCounter); | |
75 } | |
76 | |
77 std::unique_ptr<V8PerContextData> V8PerContextData::Create( | |
78 v8::Local<v8::Context> context) { | |
79 return WTF::WrapUnique(new V8PerContextData(context)); | |
80 } | |
81 | |
82 V8PerContextData* V8PerContextData::From(v8::Local<v8::Context> context) { | |
83 return ScriptState::From(context)->PerContextData(); | |
84 } | |
85 | |
86 v8::Local<v8::Object> V8PerContextData::CreateWrapperFromCacheSlowCase( | |
87 const WrapperTypeInfo* type) { | |
88 DCHECK(!error_prototype_.IsEmpty()); | |
89 | |
90 v8::Context::Scope scope(GetContext()); | |
91 v8::Local<v8::Function> interface_object = ConstructorForType(type); | |
92 if (interface_object.IsEmpty()) | |
93 return v8::Local<v8::Object>(); | |
94 v8::Local<v8::Object> instance_template; | |
95 if (!V8ObjectConstructor::NewInstance(isolate_, interface_object) | |
96 .ToLocal(&instance_template)) | |
97 return v8::Local<v8::Object>(); | |
98 wrapper_boilerplates_.Set(type, instance_template); | |
99 return instance_template->Clone(); | |
100 } | |
101 | |
102 v8::Local<v8::Function> V8PerContextData::ConstructorForTypeSlowCase( | |
103 const WrapperTypeInfo* type) { | |
104 DCHECK(!error_prototype_.IsEmpty()); | |
105 | |
106 v8::Local<v8::Context> current_context = GetContext(); | |
107 v8::Context::Scope scope(current_context); | |
108 const DOMWrapperWorld& world = DOMWrapperWorld::World(current_context); | |
109 // We shouldn't reach this point for the types that are implemented in v8 such | |
110 // as typed arrays and hence don't have domTemplateFunction. | |
111 DCHECK(type->dom_template_function); | |
112 v8::Local<v8::FunctionTemplate> interface_template = | |
113 type->domTemplate(isolate_, world); | |
114 // Getting the function might fail if we're running out of stack or memory. | |
115 v8::Local<v8::Function> interface_object; | |
116 if (!interface_template->GetFunction(current_context) | |
117 .ToLocal(&interface_object)) | |
118 return v8::Local<v8::Function>(); | |
119 | |
120 if (type->parent_class) { | |
121 v8::Local<v8::Object> prototype_template = | |
122 ConstructorForType(type->parent_class); | |
123 if (prototype_template.IsEmpty()) | |
124 return v8::Local<v8::Function>(); | |
125 if (!V8CallBoolean(interface_object->SetPrototype(current_context, | |
126 prototype_template))) | |
127 return v8::Local<v8::Function>(); | |
128 } | |
129 | |
130 v8::Local<v8::Value> prototype_value; | |
131 if (!interface_object | |
132 ->Get(current_context, V8AtomicString(isolate_, "prototype")) | |
133 .ToLocal(&prototype_value) || | |
134 !prototype_value->IsObject()) | |
135 return v8::Local<v8::Function>(); | |
136 v8::Local<v8::Object> prototype_object = prototype_value.As<v8::Object>(); | |
137 if (prototype_object->InternalFieldCount() == | |
138 kV8PrototypeInternalFieldcount && | |
139 type->wrapper_type_prototype == | |
140 WrapperTypeInfo::kWrapperTypeObjectPrototype) | |
141 prototype_object->SetAlignedPointerInInternalField( | |
142 kV8PrototypeTypeIndex, const_cast<WrapperTypeInfo*>(type)); | |
143 type->PreparePrototypeAndInterfaceObject(current_context, world, | |
144 prototype_object, interface_object, | |
145 interface_template); | |
146 if (type->wrapper_type_prototype == | |
147 WrapperTypeInfo::kWrapperTypeExceptionPrototype) { | |
148 if (!V8CallBoolean(prototype_object->SetPrototype( | |
149 current_context, error_prototype_.NewLocal(isolate_)))) | |
150 return v8::Local<v8::Function>(); | |
151 } | |
152 | |
153 // Origin Trials | |
154 InstallConditionalFeatures(type, ScriptState::From(current_context), | |
155 prototype_object, interface_object); | |
156 | |
157 constructor_map_.Set(type, interface_object); | |
158 | |
159 return interface_object; | |
160 } | |
161 | |
162 v8::Local<v8::Object> V8PerContextData::PrototypeForType( | |
163 const WrapperTypeInfo* type) { | |
164 v8::Local<v8::Object> constructor = ConstructorForType(type); | |
165 if (constructor.IsEmpty()) | |
166 return v8::Local<v8::Object>(); | |
167 v8::Local<v8::Value> prototype_value; | |
168 if (!constructor->Get(GetContext(), V8String(isolate_, "prototype")) | |
169 .ToLocal(&prototype_value) || | |
170 !prototype_value->IsObject()) | |
171 return v8::Local<v8::Object>(); | |
172 return prototype_value.As<v8::Object>(); | |
173 } | |
174 | |
175 bool V8PerContextData::GetExistingConstructorAndPrototypeForType( | |
176 const WrapperTypeInfo* type, | |
177 v8::Local<v8::Object>* prototype_object, | |
178 v8::Local<v8::Function>* interface_object) { | |
179 *interface_object = constructor_map_.Get(type); | |
180 if (interface_object->IsEmpty()) { | |
181 *prototype_object = v8::Local<v8::Object>(); | |
182 return false; | |
183 } | |
184 *prototype_object = PrototypeForType(type); | |
185 DCHECK(!prototype_object->IsEmpty()); | |
186 return true; | |
187 } | |
188 | |
189 void V8PerContextData::AddCustomElementBinding( | |
190 std::unique_ptr<V0CustomElementBinding> binding) { | |
191 custom_element_bindings_.push_back(std::move(binding)); | |
192 } | |
193 | |
194 void V8PerContextData::AddData(const char* key, Data* data) { | |
195 data_map_.Set(key, data); | |
196 } | |
197 | |
198 void V8PerContextData::ClearData(const char* key) { | |
199 data_map_.erase(key); | |
200 } | |
201 | |
202 V8PerContextData::Data* V8PerContextData::GetData(const char* key) { | |
203 return data_map_.at(key); | |
204 } | |
205 | |
206 } // namespace blink | |
OLD | NEW |