1 /* 2 * Copyright (C) 2009 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "bindings/v8/V8PerIsolateData.h" 28 29 #include "bindings/v8/DOMDataStore.h" 30 #include "bindings/v8/ScriptGCEvent.h" 31 #include "bindings/v8/ScriptProfiler.h" 32 #include "bindings/v8/V8Binding.h" 33 #include "bindings/v8/V8HiddenPropertyName.h" 34 #include "bindings/v8/V8ObjectConstructor.h" 35 #include "bindings/v8/V8ScriptRunner.h" 36 37 namespace WebCore { 38 39 V8PerIsolateData::V8PerIsolateData(v8::Isolate* isolate) 40 : m_isolate(isolate) 41 , m_stringCache(adoptPtr(new StringCache())) 42 , m_workerDomDataStore(0) 43 , m_hiddenPropertyName(adoptPtr(new V8HiddenPropertyName())) 44 , m_constructorMode(ConstructorMode::CreateNewObject) 45 , m_recursionLevel(0) 46 #ifndef NDEBUG 47 , m_internalScriptRecursionLevel(0) 48 #endif 49 , m_gcEventData(adoptPtr(new GCEventData())) 50 , m_shouldCollectGarbageSoon(false) 51 { 52 } 53 54 V8PerIsolateData::~V8PerIsolateData() 55 { 56 } 57 58 V8PerIsolateData* V8PerIsolateData::create(v8::Isolate* isolate) 59 { 60 ASSERT(isolate); 61 ASSERT(!isolate->GetData(gin::kEmbedderBlink)); 62 V8PerIsolateData* data = new V8PerIsolateData(isolate); 63 isolate->SetData(gin::kEmbedderBlink, data); 64 return data; 65 } 66 67 void V8PerIsolateData::ensureInitialized(v8::Isolate* isolate) 68 { 69 ASSERT(isolate); 70 if (!isolate->GetData(gin::kEmbedderBlink)) 71 create(isolate); 72 } 73 74 v8::Persistent<v8::Value>& V8PerIsolateData::ensureLiveRoot() 75 { 76 if (m_liveRoot.isEmpty()) 77 m_liveRoot.set(m_isolate, v8::Null(m_isolate)); 78 return m_liveRoot.getUnsafe(); 79 } 80 81 void V8PerIsolateData::dispose(v8::Isolate* isolate) 82 { 83 void* data = isolate->GetData(gin::kEmbedderBlink); 84 delete static_cast<V8PerIsolateData*>(data); 85 isolate->SetData(gin::kEmbedderBlink, 0); 86 } 87 88 v8::Handle<v8::FunctionTemplate> V8PerIsolateData::toStringTemplate() 89 { 90 if (m_toStringTemplate.isEmpty()) 91 m_toStringTemplate.set(m_isolate, v8::FunctionTemplate::New(m_isolate, constructorOfToString)); 92 return m_toStringTemplate.newLocal(m_isolate); 93 } 94 95 v8::Handle<v8::FunctionTemplate> V8PerIsolateData::privateTemplate(WrapperWorldType currentWorldType, void* privatePointer, v8::FunctionCallback callback, v8::Handle<v8::Value> data, v8::Handle<v8::Signature> signature, int length) 96 { 97 TemplateMap& templates = templateMap(currentWorldType); 98 TemplateMap::iterator result = templates.find(privatePointer); 99 if (result != templates.end()) 100 return result->value.newLocal(m_isolate); 101 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(m_isolate, callback, data, signature, length); 102 templates.add(privatePointer, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); 103 return templ; 104 } 105 106 v8::Handle<v8::FunctionTemplate> V8PerIsolateData::privateTemplateIfExists(WrapperWorldType currentWorldType, void* privatePointer) 107 { 108 TemplateMap& templates = templateMap(currentWorldType); 109 TemplateMap::iterator result = templates.find(privatePointer); 110 if (result != templates.end()) 111 return result->value.newLocal(m_isolate); 112 return v8::Local<v8::FunctionTemplate>(); 113 } 114 115 void V8PerIsolateData::setPrivateTemplate(WrapperWorldType currentWorldType, void* privatePointer, v8::Handle<v8::FunctionTemplate> templ) 116 { 117 templateMap(currentWorldType).add(privatePointer, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); 118 } 119 120 v8::Handle<v8::FunctionTemplate> V8PerIsolateData::rawDOMTemplate(const WrapperTypeInfo* info, WrapperWorldType currentWorldType) 121 { 122 TemplateMap& templates = rawDOMTemplateMap(currentWorldType); 123 TemplateMap::iterator result = templates.find(info); 124 if (result != templates.end()) 125 return result->value.newLocal(m_isolate); 126 127 v8::EscapableHandleScope handleScope(m_isolate); 128 v8::Local<v8::FunctionTemplate> templ = createRawTemplate(m_isolate); 129 templates.add(info, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); 130 return handleScope.Escape(templ); 131 } 132 133 v8::Local<v8::Context> V8PerIsolateData::ensureRegexContext() 134 { 135 if (m_regexContext.isEmpty()) { 136 v8::HandleScope handleScope(m_isolate); 137 m_regexContext.set(m_isolate, v8::Context::New(m_isolate)); 138 } 139 return m_regexContext.newLocal(m_isolate); 140 } 141 142 bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value, WrapperWorldType currentWorldType) 143 { 144 TemplateMap& templates = rawDOMTemplateMap(currentWorldType); 145 TemplateMap::iterator result = templates.find(info); 146 if (result == templates.end()) 147 return false; 148 v8::HandleScope handleScope(m_isolate); 149 return result->value.newLocal(m_isolate)->HasInstance(value); 150 } 151 152 void V8PerIsolateData::constructorOfToString(const v8::FunctionCallbackInfo<v8::Value>& info) 153 { 154 // The DOM constructors' toString functions grab the current toString 155 // for Functions by taking the toString function of itself and then 156 // calling it with the constructor as its receiver. This means that 157 // changes to the Function prototype chain or toString function are 158 // reflected when printing DOM constructors. The only wart is that 159 // changes to a DOM constructor's toString's toString will cause the 160 // toString of the DOM constructor itself to change. This is extremely 161 // obscure and unlikely to be a problem. 162 v8::Handle<v8::Value> value = info.Callee()->Get(v8AtomicString(info.GetIsolate(), "toString")); 163 if (!value->IsFunction()) { 164 v8SetReturnValue(info, v8::String::Empty(info.GetIsolate())); 165 return; 166 } 167 v8SetReturnValue(info, V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(value), info.This(), 0, 0, v8::Isolate::GetCurrent())); 168 } 169 170 } // namespace WebCore 171