v8::Handle<v8::Value> V8Proxy::throwError(ErrorType type, const char* message) { switch (type) { case RangeError: return v8::ThrowException(v8::Exception::RangeError(v8String(message))); case ReferenceError: return v8::ThrowException(v8::Exception::ReferenceError(v8String(message))); case SyntaxError: return v8::ThrowException(v8::Exception::SyntaxError(v8String(message))); case TypeError: return v8::ThrowException(v8::Exception::TypeError(v8String(message))); case GeneralError: return v8::ThrowException(v8::Exception::Error(v8String(message))); default: ASSERT_NOT_REACHED(); return notHandledByInterceptor(); } }
v8::Handle<v8::Value> V8WebGLRenderingContext::getParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getParameter()"); if (args.Length() != 1) { V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } ExceptionCode ec = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); unsigned pname = toInt32(args[0]); WebGLGetInfo info = context->getParameter(pname, ec); if (ec) { V8Proxy::setDOMException(ec); return v8::Undefined(); } return toV8Object(info); }
static v8::Handle<v8::Value> bindVertexArrayOESCallback(const v8::Arguments& args) { INC_STATS("DOM.OESVertexArrayObject.bindVertexArrayOES"); OESVertexArrayObject* imp = V8OESVertexArrayObject::toNative(args.Holder()); ExceptionCode ec = 0; { if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLVertexArrayObjectOES::HasInstance(args[0])) { V8Proxy::throwTypeError(); return notHandledByInterceptor(); } EXCEPTION_BLOCK(WebGLVertexArrayObjectOES*, arrayObject, V8WebGLVertexArrayObjectOES::HasInstance(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined)) ? V8WebGLVertexArrayObjectOES::toNative(v8::Handle<v8::Object>::Cast(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined))) : 0); imp->bindVertexArrayOES(arrayObject, ec); if (UNLIKELY(ec)) goto fail; return v8::Handle<v8::Value>(); } fail: V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); }
static v8::Handle<v8::Value> storageSetter(v8::Local<v8::String> v8Name, v8::Local<v8::Value> v8Value, const v8::AccessorInfo& info) { Storage* storage = V8Storage::toNative(info.Holder()); String name = toWebCoreString(v8Name); String value = toWebCoreString(v8Value); // Silently ignore length (rather than letting the bindings raise an exception). if (name == "length") return v8Value; v8::Handle<v8::Value> prototypeValue = info.Holder()->GetRealNamedPropertyInPrototypeChain(v8Name); if (!prototypeValue.IsEmpty()) return notHandledByInterceptor(); ExceptionCode ec = 0; storage->setItem(name, value, ec); if (ec) return throwError(ec); return v8Value; }
static v8::Handle<v8::Value> initializeCallback(const v8::Arguments& args) { INC_STATS("DOM.SVGPathSegList.initialize"); if (args.Length() < 1) return throwError("Not enough arguments", V8Proxy::TypeError); RefPtr<SVGPathSegListPropertyTearOff > imp = V8SVGPathSegList::toNative(args.Holder()); ExceptionCode ec = 0; { if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8SVGPathSeg::HasInstance(args[0])) { V8Proxy::throwTypeError(); return notHandledByInterceptor(); } EXCEPTION_BLOCK(SVGPathSeg*, newItem, V8SVGPathSeg::HasInstance(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined)) ? V8SVGPathSeg::toNative(v8::Handle<v8::Object>::Cast(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined))) : 0); RefPtr<SVGPathSeg> result = imp->initialize(newItem, ec); if (UNLIKELY(ec)) goto fail; return toV8(result.release()); } fail: V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); }
static v8::Handle<v8::Value> multiplyCallback(const v8::Arguments& args) { INC_STATS("DOM.SVGMatrix.multiply"); if (args.Length() < 1) return throwError("Not enough arguments", V8Proxy::TypeError); RefPtr<SVGPropertyTearOff<SVGMatrix> > wrapper = V8SVGMatrix::toNative(args.Holder()); if (wrapper->role() == AnimValRole) { V8Proxy::setDOMException(NO_MODIFICATION_ALLOWED_ERR); return v8::Handle<v8::Value>(); } SVGMatrix& impInstance = wrapper->propertyReference(); SVGMatrix* imp = &impInstance; if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8SVGMatrix::HasInstance(args[0])) { V8Proxy::throwTypeError(); return notHandledByInterceptor(); } EXCEPTION_BLOCK(RefPtr<SVGPropertyTearOff<SVGMatrix> >, secondMatrix, V8SVGMatrix::HasInstance(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined)) ? V8SVGMatrix::toNative(v8::Handle<v8::Object>::Cast(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined))) : 0); if (!secondMatrix) { V8Proxy::setDOMException(WebCore::TYPE_MISMATCH_ERR); return v8::Handle<v8::Value>(); } return toV8(WTF::getPtr(SVGPropertyTearOff<SVGMatrix>::create(imp->multiply(secondMatrix->propertyReference())))); }
static v8::Handle<v8::Value> replaceItemCallback(const v8::Arguments& args) { INC_STATS("DOM.SVGLengthList.replaceItem"); if (args.Length() < 2) return throwError("Not enough arguments", V8Proxy::TypeError); RefPtr<SVGListPropertyTearOff<SVGLengthList> > imp = V8SVGLengthList::toNative(args.Holder()); ExceptionCode ec = 0; { if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8SVGLength::HasInstance(args[0])) { V8Proxy::throwTypeError(); return notHandledByInterceptor(); } EXCEPTION_BLOCK(RefPtr<SVGPropertyTearOff<SVGLength> >, item, V8SVGLength::HasInstance(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined)) ? V8SVGLength::toNative(v8::Handle<v8::Object>::Cast(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined))) : 0); EXCEPTION_BLOCK(unsigned, index, toUInt32(MAYBE_MISSING_PARAMETER(args, 1, MissingIsUndefined))); RefPtr<SVGPropertyTearOff<SVGLength> > result = imp->replaceItem(item, index, ec); if (UNLIKELY(ec)) goto fail; return toV8(result.release()); } fail: V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); }
static v8::Handle<v8::Value> getObjectParameter(const v8::Arguments& args, ObjectType objectType) { if (args.Length() != 2) { V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } ExceptionCode ec = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); unsigned target = toInt32(args[0]); unsigned pname = toInt32(args[1]); WebGLGetInfo info; switch (objectType) { case kBuffer: info = context->getBufferParameter(target, pname, ec); break; case kRenderbuffer: info = context->getRenderbufferParameter(target, pname, ec); break; case kTexture: info = context->getTexParameter(target, pname, ec); break; case kVertexAttrib: // target => index info = context->getVertexAttrib(target, pname, ec); break; default: notImplemented(); break; } if (ec) { V8Proxy::setDOMException(ec); return v8::Undefined(); } return toV8Object(info); }
v8::Local<v8::Value> V8Proxy::runScript(v8::Handle<v8::Script> script, bool isInlineCode) { if (script.IsEmpty()) return notHandledByInterceptor(); /// M: add for systrace TRACE_METHOD() V8GCController::checkMemoryUsage(); // Compute the source string and prevent against infinite recursion. if (m_recursion >= kMaxRecursionDepth) { v8::Local<v8::String> code = v8ExternalString("throw RangeError('Recursion too deep')"); // FIXME: Ideally, we should be able to re-use the origin of the // script passed to us as the argument instead of using an empty string // and 0 baseLine. script = compileScript(code, "", TextPosition0::minimumPosition()); } if (handleOutOfMemory()) ASSERT(script.IsEmpty()); if (script.IsEmpty()) return notHandledByInterceptor(); // Save the previous value of the inlineCode flag and update the flag for // the duration of the script invocation. bool previousInlineCode = inlineCode(); setInlineCode(isInlineCode); // Run the script and keep track of the current recursion depth. v8::Local<v8::Value> result; v8::TryCatch tryCatch; tryCatch.SetVerbose(true); { // See comment in V8Proxy::callFunction. m_frame->keepAlive(); m_recursion++; result = script->Run(); m_recursion--; } // Release the storage mutex if applicable. didLeaveScriptContext(); if (handleOutOfMemory()) ASSERT(result.IsEmpty()); // Handle V8 internal error situation (Out-of-memory). if (tryCatch.HasCaught()) { ASSERT(result.IsEmpty()); return notHandledByInterceptor(); } if (result.IsEmpty()) return notHandledByInterceptor(); // Restore inlineCode flag. setInlineCode(previousInlineCode); if (v8::V8::IsDead()) handleFatalErrorInV8(); return result; }
static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args, int matrixSize) { // Forms: // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data); // * glUniformMatrix2fv(GLint location, GLboolean transpose, Float32Array data); // * glUniformMatrix3fv(GLint location, GLboolean transpose, Array data); // * glUniformMatrix3fv(GLint location, GLboolean transpose, Float32Array data); // * glUniformMatrix4fv(GLint location, GLboolean transpose, Array data); // * glUniformMatrix4fv(GLint location, GLboolean transpose, Float32Array data); // // FIXME: need to change to accept Float32Array as well. if (args.Length() != 3) { V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) { V8Proxy::throwTypeError(); return notHandledByInterceptor(); } bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); bool transpose = args[1]->BooleanValue(); if (V8Float32Array::HasInstance(args[2])) { Float32Array* array = V8Float32Array::toNative(args[2]->ToObject()); ASSERT(array != NULL); ExceptionCode ec = 0; switch (matrixSize) { case 2: context->uniformMatrix2fv(location, transpose, array, ec); break; case 3: context->uniformMatrix3fv(location, transpose, array, ec); break; case 4: context->uniformMatrix4fv(location, transpose, array, ec); break; default: ASSERT_NOT_REACHED(); break; } if (ec) V8Proxy::setDOMException(ec); return v8::Undefined(); } if (args[2].IsEmpty() || !args[2]->IsArray()) { V8Proxy::throwTypeError(); return notHandledByInterceptor(); } v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(args[2]); uint32_t len = array->Length(); float* data = jsArrayToFloatArray(array, len); if (!data) { // FIXME: consider different / better exception type. V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } ExceptionCode ec = 0; switch (matrixSize) { case 2: context->uniformMatrix2fv(location, transpose, data, len, ec); break; case 3: context->uniformMatrix3fv(location, transpose, data, len, ec); break; case 4: context->uniformMatrix4fv(location, transpose, data, len, ec); break; default: ASSERT_NOT_REACHED(); break; } fastFree(data); if (ec) V8Proxy::setDOMException(ec); return v8::Undefined(); }
static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args, FunctionToCall functionToCall) { // Forms: // * glUniform1iv(GLUniformLocation location, Array data); // * glUniform1iv(GLUniformLocation location, Int32Array data); // * glUniform2iv(GLUniformLocation location, Array data); // * glUniform2iv(GLUniformLocation location, Int32Array data); // * glUniform3iv(GLUniformLocation location, Array data); // * glUniform3iv(GLUniformLocation location, Int32Array data); // * glUniform4iv(GLUniformLocation location, Array data); // * glUniform4iv(GLUniformLocation location, Int32Array data); if (args.Length() != 2) { V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) { V8Proxy::throwTypeError(); return notHandledByInterceptor(); } bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); if (V8Int32Array::HasInstance(args[1])) { Int32Array* array = V8Int32Array::toNative(args[1]->ToObject()); ASSERT(array != NULL); ExceptionCode ec = 0; switch (functionToCall) { case kUniform1v: context->uniform1iv(location, array, ec); break; case kUniform2v: context->uniform2iv(location, array, ec); break; case kUniform3v: context->uniform3iv(location, array, ec); break; case kUniform4v: context->uniform4iv(location, array, ec); break; default: ASSERT_NOT_REACHED(); break; } if (ec) V8Proxy::setDOMException(ec); return v8::Undefined(); } if (args[1].IsEmpty() || !args[1]->IsArray()) { V8Proxy::throwTypeError(); return notHandledByInterceptor(); } v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(args[1]); uint32_t len = array->Length(); int* data = jsArrayToIntArray(array, len); if (!data) { // FIXME: consider different / better exception type. V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } ExceptionCode ec = 0; switch (functionToCall) { case kUniform1v: context->uniform1iv(location, data, len, ec); break; case kUniform2v: context->uniform2iv(location, data, len, ec); break; case kUniform3v: context->uniform3iv(location, data, len, ec); break; case kUniform4v: context->uniform4iv(location, data, len, ec); break; default: ASSERT_NOT_REACHED(); break; } fastFree(data); if (ec) V8Proxy::setDOMException(ec); return v8::Undefined(); }
v8::Handle<v8::Value> V8CanvasRenderingContext2D::drawImageCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.drawImage()"); CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { ExceptionCode ec = 0; HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: context->drawImage(imageElement, toFloat(args[1]), toFloat(args[2])); break; case 5: context->drawImage(imageElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); if (ec != 0) { V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; case 9: context->drawImage(imageElement, FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])), FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), ec); if (ec != 0) { V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; default: return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); } return v8::Undefined(); } // HTMLCanvasElement if (V8HTMLCanvasElement::HasInstance(arg)) { ExceptionCode ec = 0; HTMLCanvasElement* canvasElement = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: context->drawImage(canvasElement, toFloat(args[1]), toFloat(args[2])); break; case 5: context->drawImage(canvasElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); if (ec != 0) { V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; case 9: context->drawImage(canvasElement, FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])), FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), ec); if (ec != 0) { V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; default: return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); } return v8::Undefined(); } #if ENABLE(VIDEO) // HTMLVideoElement if (V8HTMLVideoElement::HasInstance(arg)) { ExceptionCode ec = 0; HTMLVideoElement* videoElement = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: context->drawImage(videoElement, toFloat(args[1]), toFloat(args[2])); break; case 5: context->drawImage(videoElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); if (ec != 0) { V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; case 9: context->drawImage(videoElement, FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])), FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), ec); if (ec != 0) { V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; default: return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); } return v8::Undefined(); } #endif V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return notHandledByInterceptor(); }
// A JS object of type EventTarget is limited to a small number of possible classes. // Check EventTarget.h for new type conversion methods v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* target) { if (!target) return v8::Null(); #if ENABLE(SVG) if (SVGElementInstance* instance = target->toSVGElementInstance()) return toV8(instance); #endif #if ENABLE(WORKERS) if (Worker* worker = target->toWorker()) return toV8(worker); if (DedicatedWorkerContext* workerContext = target->toDedicatedWorkerContext()) return toV8(workerContext); #endif // WORKERS #if ENABLE(SHARED_WORKERS) if (SharedWorker* sharedWorker = target->toSharedWorker()) return toV8(sharedWorker); if (SharedWorkerContext* sharedWorkerContext = target->toSharedWorkerContext()) return toV8(sharedWorkerContext); #endif // SHARED_WORKERS #if ENABLE(NOTIFICATIONS) if (Notification* notification = target->toNotification()) return toV8(notification); #endif #if ENABLE(INDEXED_DATABASE) if (IDBDatabase* idbDatabase = target->toIDBDatabase()) return toV8(idbDatabase); if (IDBRequest* idbRequest = target->toIDBRequest()) return toV8(idbRequest); if (IDBTransaction* idbTransaction = target->toIDBTransaction()) return toV8(idbTransaction); #endif #if ENABLE(WEB_SOCKETS) if (WebSocket* webSocket = target->toWebSocket()) return toV8(webSocket); #endif if (Node* node = target->toNode()) return toV8(node); if (DOMWindow* domWindow = target->toDOMWindow()) return toV8(domWindow); // XMLHttpRequest is created within its JS counterpart. if (XMLHttpRequest* xmlHttpRequest = target->toXMLHttpRequest()) { v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xmlHttpRequest); ASSERT(!wrapper.IsEmpty()); return wrapper; } // MessagePort is created within its JS counterpart if (MessagePort* port = target->toMessagePort()) { v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port); ASSERT(!wrapper.IsEmpty()); return wrapper; } if (XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload()) { v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload); ASSERT(!wrapper.IsEmpty()); return wrapper; } #if ENABLE(OFFLINE_WEB_APPLICATIONS) if (DOMApplicationCache* domAppCache = target->toDOMApplicationCache()) return toV8(domAppCache); #endif #if ENABLE(EVENTSOURCE) if (EventSource* eventSource = target->toEventSource()) return toV8(eventSource); #endif #if ENABLE(BLOB) if (FileReader* fileReader = target->toFileReader()) return toV8(fileReader); #endif #if ENABLE(FILE_SYSTEM) if (FileWriter* fileWriter = target->toFileWriter()) return toV8(fileWriter); #endif #if ENABLE(WEB_AUDIO) if (JavaScriptAudioNode* jsAudioNode = target->toJavaScriptAudioNode()) return toV8(jsAudioNode); if (AudioContext* audioContext = target->toAudioContext()) return toV8(audioContext); #endif ASSERT(0); return notHandledByInterceptor(); }