2 * Copyright (C) 2009 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
34 #include "BindingSecurity.h"
35 #include "DOMDataStore.h"
36 #include "MathExtras.h"
37 #include "PlatformString.h"
38 #include "V8DOMWrapper.h"
39 #include "V8GCController.h"
40 #include "V8HiddenPropertyName.h"
41 #include <wtf/text/AtomicString.h>
51 // FIXME: Remove V8Binding.
54 typedef BindingSecurity<V8Binding> V8BindingSecurity;
60 v8::Local<v8::String> v8ExternalString(StringImpl* stringImpl)
62 if (m_lastStringImpl.get() == stringImpl) {
63 ASSERT(!m_lastV8String.IsNearDeath());
64 ASSERT(!m_lastV8String.IsEmpty());
65 return v8::Local<v8::String>::New(m_lastV8String);
68 return v8ExternalStringSlow(stringImpl);
74 m_lastV8String.Clear();
77 void remove(StringImpl*);
80 v8::Local<v8::String> v8ExternalStringSlow(StringImpl*);
82 HashMap<StringImpl*, v8::String*> m_stringCache;
83 v8::Persistent<v8::String> m_lastV8String;
84 // Note: RefPtr is a must as we cache by StringImpl* equality, not identity
85 // hence lastStringImpl might be not a key of the cache (in sense of identity)
86 // and hence it's not refed on addition.
87 RefPtr<StringImpl> m_lastStringImpl;
90 class AllowAllocation;
93 typedef HashMap<v8::Value*, GlobalHandleInfo*> GlobalHandleMap;
96 class V8BindingPerIsolateData {
98 static V8BindingPerIsolateData* create(v8::Isolate*);
99 static void ensureInitialized(v8::Isolate*);
100 static V8BindingPerIsolateData* get(v8::Isolate* isolate)
102 ASSERT(isolate->GetData());
103 return static_cast<V8BindingPerIsolateData*>(isolate->GetData());
106 static V8BindingPerIsolateData* current()
108 return get(v8::Isolate::GetCurrent());
110 static void dispose(v8::Isolate*);
112 typedef HashMap<WrapperTypeInfo*, v8::Persistent<v8::FunctionTemplate> > TemplateMap;
114 TemplateMap& rawTemplateMap() { return m_rawTemplates; }
115 TemplateMap& templateMap() { return m_templates; }
116 v8::Persistent<v8::String>& toStringName() { return m_toStringName; }
117 v8::Persistent<v8::FunctionTemplate>& toStringTemplate() { return m_toStringTemplate; }
119 v8::Persistent<v8::FunctionTemplate>& lazyEventListenerToStringTemplate()
121 return m_lazyEventListenerToStringTemplate;
124 StringCache* stringCache() { return &m_stringCache; }
126 DOMDataList& allStores() { return m_domDataList; }
128 V8HiddenPropertyName* hiddenPropertyName() { return &m_hiddenPropertyName; }
130 void registerDOMDataStore(DOMDataStore* domDataStore)
132 m_domDataList.append(domDataStore);
135 void unregisterDOMDataStore(DOMDataStore* domDataStore)
137 ASSERT(m_domDataList.find(domDataStore));
138 m_domDataList.remove(m_domDataList.find(domDataStore));
142 DOMDataStore* domDataStore() { return m_domDataStore; }
143 // DOMDataStore is owned outside V8BindingPerIsolateData.
144 void setDOMDataStore(DOMDataStore* store) { m_domDataStore = store; }
147 GlobalHandleMap& globalHandleMap() { return m_globalHandleMap; }
151 explicit V8BindingPerIsolateData(v8::Isolate*);
152 ~V8BindingPerIsolateData();
154 TemplateMap m_rawTemplates;
155 TemplateMap m_templates;
156 v8::Persistent<v8::String> m_toStringName;
157 v8::Persistent<v8::FunctionTemplate> m_toStringTemplate;
158 v8::Persistent<v8::FunctionTemplate> m_lazyEventListenerToStringTemplate;
159 StringCache m_stringCache;
161 DOMDataList m_domDataList;
162 DOMDataStore* m_domDataStore;
164 V8HiddenPropertyName m_hiddenPropertyName;
166 bool m_currentAllocationsAllowed;
167 friend class AllowAllocation;
170 GlobalHandleMap m_globalHandleMap;
174 class AllowAllocation {
178 V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
179 m_previous = data->m_currentAllocationsAllowed;
180 data->m_currentAllocationsAllowed = true;
185 V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
186 data->m_currentAllocationsAllowed = m_previous;
189 static bool current() { return V8BindingPerIsolateData::current()->m_currentAllocationsAllowed; }
195 class SafeAllocation {
197 static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>);
198 static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>);
199 static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]);
202 v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function)
204 if (function.IsEmpty())
205 return v8::Local<v8::Object>();
206 AllowAllocation allow;
207 return function->NewInstance();
210 v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::ObjectTemplate> objectTemplate)
212 if (objectTemplate.IsEmpty())
213 return v8::Local<v8::Object>();
214 AllowAllocation allow;
215 return objectTemplate->NewInstance();
218 v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[])
220 if (function.IsEmpty())
221 return v8::Local<v8::Object>();
222 AllowAllocation allow;
223 return function->NewInstance(argc, argv);
233 template <typename StringType>
234 StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external);
236 // Convert v8 types to a WTF::String. If the V8 string is not already
237 // an external string then it is transformed into an external string at this
238 // point to avoid repeated conversions.
239 inline String v8StringToWebCoreString(v8::Handle<v8::String> v8String)
241 return v8StringToWebCoreString<String>(v8String, Externalize);
243 String v8NonStringValueToWebCoreString(v8::Handle<v8::Value>);
244 String v8ValueToWebCoreString(v8::Handle<v8::Value> value);
246 // Convert v8 types to a WTF::AtomicString.
247 inline AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String)
249 return v8StringToWebCoreString<AtomicString>(v8String, Externalize);
251 AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value>);
252 AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value);
254 // Return a V8 external string that shares the underlying buffer with the given
255 // WebCore string. The reference counting mechanism is used to keep the
256 // underlying buffer alive while the string is still live in the V8 engine.
257 inline v8::Local<v8::String> v8ExternalString(const String& string)
259 StringImpl* stringImpl = string.impl();
261 return v8::String::Empty();
263 V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
264 return data->stringCache()->v8ExternalString(stringImpl);
267 // Convert a string to a V8 string.
268 inline v8::Handle<v8::String> v8String(const String& string)
270 return v8ExternalString(string);
273 // Enables caching v8 wrappers created for WTF::StringImpl. Currently this cache requires
274 // all the calls (both to convert WTF::String to v8::String and to GC the handle)
275 // to be performed on the main thread.
276 void enableStringImplCache();
278 // Convert a value to a 32-bit integer. The conversion fails if the
279 // value cannot be converted to an integer or converts to nan or to an infinity.
280 int toInt32(v8::Handle<v8::Value> value, bool& ok);
282 // Convert a value to a 32-bit integer assuming the conversion cannot fail.
283 inline int toInt32(v8::Handle<v8::Value> value)
286 return toInt32(value, ok);
289 // Convert a value to a 32-bit unsigned integer. The conversion fails if the
290 // value cannot be converted to an unsigned integer or converts to nan or to an infinity.
291 uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok);
293 // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail.
294 inline uint32_t toUInt32(v8::Handle<v8::Value> value)
297 return toUInt32(value, ok);
300 inline float toFloat(v8::Local<v8::Value> value)
302 return static_cast<float>(value->NumberValue());
305 inline long long toInt64(v8::Local<v8::Value> value)
307 return static_cast<long long>(value->IntegerValue());
310 // FIXME: Drop this in favor of the type specific v8ValueToWebCoreString when we rework the code generation.
311 inline String toWebCoreString(v8::Handle<v8::Value> object)
313 return v8ValueToWebCoreString(object);
316 String toWebCoreString(const v8::Arguments&, int index);
318 // The string returned by this function is still owned by the argument
319 // and will be deallocated when the argument is deallocated.
320 inline const uint16_t* fromWebCoreString(const String& str)
322 return reinterpret_cast<const uint16_t*>(str.characters());
325 bool isUndefinedOrNull(v8::Handle<v8::Value> value);
327 // Returns true if the provided object is to be considered a 'host object', as used in the
328 // HTML5 structured clone algorithm.
329 bool isHostObject(v8::Handle<v8::Object>);
331 v8::Handle<v8::Boolean> v8Boolean(bool value);
333 String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
335 AtomicString toAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
337 String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value);
339 v8::Handle<v8::String> v8UndetectableString(const String& str);
341 v8::Handle<v8::Value> v8StringOrNull(const String& str);
343 v8::Handle<v8::Value> v8StringOrUndefined(const String& str);
345 v8::Handle<v8::Value> v8StringOrFalse(const String& str);
347 double toWebCoreDate(v8::Handle<v8::Value> object);
349 v8::Handle<v8::Value> v8DateOrNull(double value);
351 v8::Persistent<v8::FunctionTemplate> createRawTemplate();
353 struct BatchedAttribute;
354 struct BatchedCallback;
356 v8::Local<v8::Signature> configureTemplate(v8::Persistent<v8::FunctionTemplate>,
357 const char* interfaceName,
358 v8::Persistent<v8::FunctionTemplate> parentClass,
360 const BatchedAttribute*,
361 size_t attributeCount,
362 const BatchedCallback*,
363 size_t callbackCount);
365 v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo&,
366 const QualifiedName&);
367 void setElementStringAttr(const v8::AccessorInfo&,
368 const QualifiedName&,
369 v8::Local<v8::Value>);
372 v8::Persistent<v8::String> getToStringName();
373 v8::Persistent<v8::FunctionTemplate> getToStringTemplate();
375 String int32ToWebCoreString(int value);
377 PassRefPtr<DOMStringList> v8ValueToWebCoreDOMStringList(v8::Handle<v8::Value>);
379 class V8ParameterBase {
381 operator String() { return toString<String>(); }
382 operator AtomicString() { return toString<AtomicString>(); }
385 V8ParameterBase(v8::Local<v8::Value> object) : m_v8Object(object), m_mode(Externalize), m_string() { }
389 if (m_v8Object.IsEmpty())
392 if (LIKELY(m_v8Object->IsString()))
395 if (LIKELY(m_v8Object->IsInt32())) {
396 setString(int32ToWebCoreString(m_v8Object->Int32Value()));
400 m_mode = DoNotExternalize;
402 m_v8Object = m_v8Object->ToString();
403 // Handle the case where an exception is thrown as part of invoking toString on the object.
404 if (block.HasCaught()) {
411 v8::Local<v8::Value> object() { return m_v8Object; }
413 void setString(const String& string)
416 m_v8Object.Clear(); // To signal that String is ready.
420 v8::Local<v8::Value> m_v8Object;
424 template <class StringType>
425 StringType toString()
427 if (LIKELY(!m_v8Object.IsEmpty()))
428 return v8StringToWebCoreString<StringType>(m_v8Object.As<v8::String>(), m_mode);
430 return StringType(m_string);
434 // V8Parameter is an adapter class that converts V8 values to Strings
435 // or AtomicStrings as appropriate, using multiple typecast operators.
436 enum V8ParameterMode {
439 WithUndefinedOrNullCheck
441 template <V8ParameterMode MODE = DefaultMode>
442 class V8Parameter: public V8ParameterBase {
444 V8Parameter(v8::Local<v8::Value> object) : V8ParameterBase(object) { }
445 V8Parameter(v8::Local<v8::Value> object, bool) : V8ParameterBase(object) { prepare(); }
450 template<> inline bool V8Parameter<DefaultMode>::prepare()
452 return V8ParameterBase::prepareBase();
455 template<> inline bool V8Parameter<WithNullCheck>::prepare()
457 if (object().IsEmpty() || object()->IsNull()) {
462 return V8ParameterBase::prepareBase();
465 template<> inline bool V8Parameter<WithUndefinedOrNullCheck>::prepare()
467 if (object().IsEmpty() || object()->IsNull() || object()->IsUndefined()) {
472 return V8ParameterBase::prepareBase();
475 enum ParameterMissingPolicy {
480 } // namespace WebCore
482 #endif // V8Binding_h