2 * Copyright (C) 2006, 2007, 2008, 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.
32 #include "V8Binding.h"
34 #include "BindingVisitors.h"
35 #include "DOMStringList.h"
38 #include "FrameLoader.h"
39 #include "FrameLoaderClient.h"
40 #include "QualifiedName.h"
42 #include "V8DOMStringList.h"
43 #include "V8DOMWindow.h"
44 #include "V8Element.h"
45 #include "V8NodeFilterCondition.h"
46 #include "V8ObjectConstructor.h"
47 #include "V8WorkerContext.h"
48 #include "V8XPathNSResolver.h"
49 #include "WebCoreMemoryInstrumentation.h"
50 #include "WorkerContext.h"
51 #include "WorkerScriptController.h"
52 #include "WorldContextHandle.h"
53 #include "XPathNSResolver.h"
54 #include <wtf/MathExtras.h>
55 #include <wtf/MainThread.h>
56 #include <wtf/StdLibExtras.h>
57 #include <wtf/Threading.h>
58 #include <wtf/text/AtomicString.h>
59 #include <wtf/text/CString.h>
60 #include <wtf/text/StringBuffer.h>
61 #include <wtf/text/StringHash.h>
62 #include <wtf/text/WTFString.h>
66 v8::Handle<v8::Value> setDOMException(int exceptionCode, v8::Isolate* isolate)
68 return V8ThrowException::setDOMException(exceptionCode, isolate);
71 v8::Handle<v8::Value> throwError(V8ErrorType errorType, const char* message, v8::Isolate* isolate)
73 return V8ThrowException::throwError(errorType, message, isolate);
76 v8::Handle<v8::Value> throwError(v8::Local<v8::Value> exception, v8::Isolate* isolate)
78 return V8ThrowException::throwError(exception, isolate);
81 v8::Handle<v8::Value> throwTypeError(const char* message, v8::Isolate* isolate)
83 return V8ThrowException::throwTypeError(message, isolate);
86 v8::Handle<v8::Value> throwNotEnoughArgumentsError(v8::Isolate* isolate)
88 return V8ThrowException::throwNotEnoughArgumentsError(isolate);
91 v8::Handle<v8::Value> v8Array(PassRefPtr<DOMStringList> stringList, v8::Isolate* isolate)
94 return v8::Array::New();
95 v8::Local<v8::Array> result = v8::Array::New(stringList->length());
96 for (unsigned i = 0; i < stringList->length(); ++i)
97 result->Set(v8Integer(i, isolate), v8String(stringList->item(i), isolate));
101 PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback)
103 return NodeFilter::create(V8NodeFilterCondition::create(callback));
106 int toInt32(v8::Handle<v8::Value> value, bool& ok)
110 // Fast case. The value is already a 32-bit integer.
111 if (value->IsInt32())
112 return value->Int32Value();
114 // Can the value be converted to a number?
115 v8::Local<v8::Number> numberObject = value->ToNumber();
116 if (numberObject.IsEmpty()) {
121 // Does the value convert to nan or to an infinity?
122 double numberValue = numberObject->Value();
123 if (std::isnan(numberValue) || std::isinf(numberValue)) {
128 // Can the value be converted to a 32-bit integer?
129 v8::Local<v8::Int32> intValue = value->ToInt32();
130 if (intValue.IsEmpty()) {
135 // Return the result of the int32 conversion.
136 return intValue->Value();
139 uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok)
143 // Fast case. The value is already a 32-bit unsigned integer.
144 if (value->IsUint32())
145 return value->Uint32Value();
147 if (value->IsInt32()) {
148 int32_t result = value->Int32Value();
153 // Can the value be converted to a number?
154 v8::Local<v8::Number> numberObject = value->ToNumber();
155 if (numberObject.IsEmpty()) {
160 // Does the value convert to nan or to an infinity?
161 double numberValue = numberObject->Value();
162 if (std::isnan(numberValue) || std::isinf(numberValue)) {
167 // Can the value be converted to a 32-bit unsigned integer?
168 v8::Local<v8::Uint32> uintValue = value->ToUint32();
169 if (uintValue.IsEmpty()) {
174 return uintValue->Value();
177 v8::Persistent<v8::FunctionTemplate> createRawTemplate(v8::Isolate* isolate)
179 v8::HandleScope scope;
180 v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8ObjectConstructor::isValidConstructorMode);
181 return v8::Persistent<v8::FunctionTemplate>::New(isolate, result);
184 PassRefPtr<DOMStringList> toDOMStringList(v8::Handle<v8::Value> value, v8::Isolate* isolate)
186 v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(value));
188 if (V8DOMStringList::HasInstance(v8Value, isolate)) {
189 RefPtr<DOMStringList> ret = V8DOMStringList::toNative(v8::Handle<v8::Object>::Cast(v8Value));
190 return ret.release();
193 if (!v8Value->IsArray())
196 RefPtr<DOMStringList> ret = DOMStringList::create();
197 v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
198 for (size_t i = 0; i < v8Array->Length(); ++i) {
199 v8::Local<v8::Value> indexedValue = v8Array->Get(v8Integer(i, isolate));
200 ret->append(toWebCoreString(indexedValue));
202 return ret.release();
205 PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value> value, v8::Isolate* isolate)
207 RefPtr<XPathNSResolver> resolver;
208 if (V8XPathNSResolver::HasInstance(value, isolate))
209 resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(value));
210 else if (value->IsObject())
211 resolver = V8CustomXPathNSResolver::create(value->ToObject(), isolate);
215 v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context> context)
217 return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype());
220 DOMWindow* toDOMWindow(v8::Handle<v8::Context> context)
222 v8::Handle<v8::Object> global = context->Global();
223 ASSERT(!global.IsEmpty());
224 global = global->FindInstanceInPrototypeChain(V8DOMWindow::GetTemplate(context->GetIsolate()));
225 ASSERT(!global.IsEmpty());
226 return V8DOMWindow::toNative(global);
229 ScriptExecutionContext* toScriptExecutionContext(v8::Handle<v8::Context> context)
231 v8::Handle<v8::Object> global = context->Global();
232 v8::Handle<v8::Object> windowWrapper = global->FindInstanceInPrototypeChain(V8DOMWindow::GetTemplate(context->GetIsolate()));
233 if (!windowWrapper.IsEmpty())
234 return V8DOMWindow::toNative(windowWrapper)->scriptExecutionContext();
236 v8::Handle<v8::Object> workerWrapper = global->FindInstanceInPrototypeChain(V8WorkerContext::GetTemplate(context->GetIsolate()));
237 if (!workerWrapper.IsEmpty())
238 return V8WorkerContext::toNative(workerWrapper)->scriptExecutionContext();
240 // FIXME: Is this line of code reachable?
244 Frame* toFrameIfNotDetached(v8::Handle<v8::Context> context)
246 DOMWindow* window = toDOMWindow(context);
247 if (window->isCurrentlyDisplayedInFrame())
248 return window->frame();
249 // We return 0 here because |context| is detached from the Frame. If we
250 // did return |frame| we could get in trouble because the frame could be
251 // navigated to another security origin.
255 v8::Local<v8::Context> toV8Context(ScriptExecutionContext* context, const WorldContextHandle& worldContext)
257 if (context->isDocument()) {
258 if (Frame* frame = static_cast<Document*>(context)->frame())
259 return worldContext.adjustedContext(frame->script());
261 } else if (context->isWorkerContext()) {
262 if (WorkerScriptController* script = static_cast<WorkerContext*>(context)->script())
263 return script->context();
266 return v8::Local<v8::Context>();
269 v8::Local<v8::Context> toV8Context(ScriptExecutionContext* context, DOMWrapperWorld* world)
271 if (context->isDocument()) {
272 if (Frame* frame = static_cast<Document*>(context)->frame()) {
273 // FIXME: Store the DOMWrapperWorld for the main world in the v8::Context so callers
274 // that are looking up their world with DOMWrapperWorld::isolatedWorld(v8::Context::GetCurrent())
275 // won't end up passing null here when later trying to get their v8::Context back.
277 return frame->script()->mainWorldContext();
278 return v8::Local<v8::Context>::New(frame->script()->windowShell(world)->context());
281 } else if (context->isWorkerContext()) {
282 if (WorkerScriptController* script = static_cast<WorkerContext*>(context)->script())
283 return script->context();
286 return v8::Local<v8::Context>();
289 bool handleOutOfMemory()
291 v8::Local<v8::Context> context = v8::Context::GetCurrent();
293 if (!context->HasOutOfMemoryException())
296 // Warning, error, disable JS for this frame?
297 Frame* frame = toFrameIfNotDetached(context);
301 frame->script()->clearForOutOfMemory();
303 #if PLATFORM(CHROMIUM)
304 frame->loader()->client()->didExhaustMemoryAvailableForScript();
307 if (Settings* settings = frame->settings())
308 settings->setScriptEnabled(false);
313 v8::Local<v8::Value> handleMaxRecursionDepthExceeded()
315 throwError(v8RangeError, "Maximum call stack size exceeded.", v8::Isolate::GetCurrent());
316 return v8::Local<v8::Value>();
319 void crashIfV8IsDead()
321 if (v8::V8::IsDead()) {
322 // FIXME: We temporarily deal with V8 internal error situations
323 // such as out-of-memory by crashing the renderer.
328 } // namespace WebCore