v8::Handle<v8::Value> V8MessageEvent::dataAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.MessageEvent.data"); MessageEvent* event = V8MessageEvent::toNative(info.Holder()); v8::Handle<v8::Value> result; switch (event->dataType()) { case MessageEvent::DataTypeSerializedScriptValue: if (SerializedScriptValue* serializedValue = event->dataAsSerializedScriptValue()) result = serializedValue->deserialize(); else result = v8::Null(); break; case MessageEvent::DataTypeString: { String stringValue = event->dataAsString(); result = v8::String::New(fromWebCoreString(stringValue), stringValue.length()); break; } case MessageEvent::DataTypeBlob: result = toV8(event->dataAsBlob()); break; case MessageEvent::DataTypeArrayBuffer: result = toV8(event->dataAsArrayBuffer()); break; } // Overwrite the data attribute so it returns the cached result in future invocations. // This custom handler (dataAccessGetter) will not be called again. v8::PropertyAttribute dataAttr = static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly); info.Holder()->ForceSet(name, result, dataAttr); return result; }
v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine) { const uint16_t* fileNameString = fromWebCoreString(fileName); v8::Handle<v8::String> name = v8::String::New(fileNameString, fileName.length()); v8::Handle<v8::Integer> line = v8::Integer::New(baseLine); v8::ScriptOrigin origin(name, line); v8::Handle<v8::Script> script = v8::Script::Compile(code, &origin); return script; }
v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition0& scriptStartPosition, v8::ScriptData* scriptData) { const uint16_t* fileNameString = fromWebCoreString(fileName); v8::Handle<v8::String> name = v8::String::New(fileNameString, fileName.length()); v8::Handle<v8::Integer> line = v8::Integer::New(scriptStartPosition.m_line.zeroBasedInt()); v8::Handle<v8::Integer> column = v8::Integer::New(scriptStartPosition.m_column.zeroBasedInt()); v8::ScriptOrigin origin(name, line, column); v8::Handle<v8::Script> script = v8::Script::Compile(code, &origin, scriptData); return script; }
void V8WebCLPlatform::getSupportedExtensionsMethodCustom(const v8::Arguments& args) { ExceptionState es(args.GetIsolate()); WebCLPlatform* platform = V8WebCLPlatform::toNative(args.Holder()); Vector<String> extensions = platform->getSupportedExtensions(es); v8::Local<v8::Array> array = v8::Array::New(extensions.size()); for (size_t i = 0; i < extensions.size(); i++) array->Set(v8::Integer::New(i), v8::String::New(fromWebCoreString(extensions[i]), extensions[i].length())); v8SetReturnValue(args, array); }
v8::Handle<v8::Value> V8WebGLRenderingContext::getSupportedExtensionsCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getSupportedExtensionsCallback()"); WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(args.Holder()); if (imp->isContextLost()) return v8::Null(); Vector<String> value = imp->getSupportedExtensions(); v8::Local<v8::Array> array = v8::Array::New(value.size()); for (size_t ii = 0; ii < value.size(); ++ii) array->Set(v8::Integer::New(ii), v8::String::New(fromWebCoreString(value[ii]), value[ii].length())); return array; }
static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& info) { switch (info.getType()) { case WebGLGetInfo::kTypeBool: return v8::Boolean::New(info.getBool()); case WebGLGetInfo::kTypeBoolArray: { const Vector<bool>& value = info.getBoolArray(); v8::Local<v8::Array> array = v8::Array::New(value.size()); for (size_t ii = 0; ii < value.size(); ++ii) array->Set(v8::Integer::New(ii), v8::Boolean::New(value[ii])); return array; } case WebGLGetInfo::kTypeFloat: return v8::Number::New(info.getFloat()); case WebGLGetInfo::kTypeInt: return v8::Integer::New(info.getInt()); case WebGLGetInfo::kTypeNull: return v8::Null(); case WebGLGetInfo::kTypeString: return v8::String::New(fromWebCoreString(info.getString()), info.getString().length()); case WebGLGetInfo::kTypeUnsignedInt: return v8::Integer::NewFromUnsigned(info.getUnsignedInt()); case WebGLGetInfo::kTypeWebGLBuffer: return toV8(info.getWebGLBuffer()); case WebGLGetInfo::kTypeWebGLFloatArray: return toV8(info.getWebGLFloatArray()); case WebGLGetInfo::kTypeWebGLFramebuffer: return toV8(info.getWebGLFramebuffer()); case WebGLGetInfo::kTypeWebGLIntArray: return toV8(info.getWebGLIntArray()); // FIXME: implement WebGLObjectArray // case WebGLGetInfo::kTypeWebGLObjectArray: case WebGLGetInfo::kTypeWebGLProgram: return toV8(info.getWebGLProgram()); case WebGLGetInfo::kTypeWebGLRenderbuffer: return toV8(info.getWebGLRenderbuffer()); case WebGLGetInfo::kTypeWebGLTexture: return toV8(info.getWebGLTexture()); case WebGLGetInfo::kTypeWebGLUnsignedByteArray: return toV8(info.getWebGLUnsignedByteArray()); case WebGLGetInfo::kTypeWebGLUnsignedIntArray: return toV8(info.getWebGLUnsignedIntArray()); case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES: return toV8(info.getWebGLVertexArrayObjectOES()); default: notImplemented(); return v8::Undefined(); } }
v8::Handle<v8::String> v8UndetectableString(const String& str) { return v8::String::NewUndetectable(fromWebCoreString(str), str.length()); }
void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context) { if (hasExistingListenerObject()) return; if (context->isDocument() && !static_cast<Document*>(context)->contentSecurityPolicy()->allowInlineEventHandlers()) return; v8::HandleScope handleScope; V8Proxy* proxy = V8Proxy::retrieve(context); if (!proxy) return; // Use the outer scope to hold context. v8::Local<v8::Context> v8Context = worldContext().adjustedContext(proxy); // Bail out if we cannot get the context. if (v8Context.IsEmpty()) return; v8::Context::Scope scope(v8Context); // FIXME: cache the wrapper function. // Nodes other than the document object, when executing inline event // handlers push document, form, and the target node on the scope chain. // We do this by using 'with' statement. // See chrome/fast/forms/form-action.html // chrome/fast/forms/selected-index-value.html // base/fast/overflow/onscroll-layer-self-destruct.html // // Don't use new lines so that lines in the modified handler // have the same numbers as in the original code. // FIXME: What about m_eventParameterName from JSLazyEventListener? // FIXME: This approach is a giant hack! What if m_code escapes to run // arbitrary script? String code = "(function (evt) {" \ "with (this.ownerDocument ? this.ownerDocument : {}) {" \ "with (this.form ? this.form : {}) {" \ "with (this) {" \ "return (function(evt){"; code.append(m_code); // Insert '\n' otherwise //-style comments could break the handler. code.append( "\n}).call(this, evt);}}}})"); v8::Handle<v8::String> codeExternalString = v8ExternalString(code); v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_sourceURL, m_position); if (!script.IsEmpty()) { v8::Local<v8::Value> value = proxy->runScript(script, false); if (!value.IsEmpty()) { ASSERT(value->IsFunction()); v8::Local<v8::Function> wrappedFunction = v8::Local<v8::Function>::Cast(value); // Change the toString function on the wrapper function to avoid it // returning the source for the actual wrapper function. Instead it // returns source for a clean wrapper function with the event // argument wrapping the event source code. The reason for this is // that some web sites use toString on event functions and eval the // source returned (sometimes a RegExp is applied as well) for some // other use. That fails miserably if the actual wrapper source is // returned. v8::Persistent<v8::FunctionTemplate>& toStringTemplate = V8BindingPerIsolateData::current()->lazyEventListenerToStringTemplate(); if (toStringTemplate.IsEmpty()) toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8LazyEventListenerToString)); v8::Local<v8::Function> toStringFunction; if (!toStringTemplate.IsEmpty()) toStringFunction = toStringTemplate->GetFunction(); if (!toStringFunction.IsEmpty()) { String toStringResult = "function "; toStringResult.append(m_functionName); toStringResult.append("("); toStringResult.append(m_isSVGEvent ? "evt" : "event"); toStringResult.append(") {\n "); toStringResult.append(m_code); toStringResult.append("\n}"); wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(), v8ExternalString(toStringResult)); wrappedFunction->Set(v8::String::New("toString"), toStringFunction); } wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length())); setListenerObject(wrappedFunction); } } }
void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context) { if (hasExistingListenerObject()) return; if (context->isDocument() && !static_cast<Document*>(context)->contentSecurityPolicy()->allowInlineEventHandlers(m_sourceURL, m_position.m_line)) return; v8::HandleScope handleScope; V8Proxy* proxy = V8Proxy::retrieve(context); if (!proxy) return; ASSERT(context->isDocument()); if (!static_cast<Document*>(context)->frame()->script()->canExecuteScripts(NotAboutToExecuteScript)) return; // Use the outer scope to hold context. v8::Local<v8::Context> v8Context = worldContext().adjustedContext(proxy); // Bail out if we cannot get the context. if (v8Context.IsEmpty()) return; v8::Context::Scope scope(v8Context); // Nodes other than the document object, when executing inline event // handlers push document, form, and the target node on the scope chain. // We do this by using 'with' statement. // See chrome/fast/forms/form-action.html // chrome/fast/forms/selected-index-value.html // base/fast/overflow/onscroll-layer-self-destruct.html // // Don't use new lines so that lines in the modified handler // have the same numbers as in the original code. // FIXME: V8 does not allow us to programmatically create object environments so // we have to do this hack! What if m_code escapes to run arbitrary script? // // Call with 4 arguments instead of 3, pass additional null as the last parameter. // By calling the function with 4 arguments, we create a setter on arguments object // which would shadow property "3" on the prototype. String code = "(function() {" \ "arguments[3] = function() {" \ "with (this[2]) {" \ "with (this[1]) {" \ "with (this[0]) {"; code.append("return function("); code.append(m_eventParameterName); code.append(") {"); code.append(m_code); // Insert '\n' otherwise //-style comments could break the handler. code.append("\n};}}}};"); code.append("return arguments[3]();})"); v8::Handle<v8::String> codeExternalString = v8ExternalString(code); v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_sourceURL, m_position); if (script.IsEmpty()) return; // FIXME: Remove this code when we stop doing the 'with' hack above. v8::Local<v8::Value> value; { V8RecursionScope::MicrotaskSuppression scope; value = script->Run(); } if (value.IsEmpty()) return; // Call the outer function to get the inner function. ASSERT(value->IsFunction()); v8::Local<v8::Function> intermediateFunction = value.As<v8::Function>(); HTMLFormElement* formElement = 0; if (m_node && m_node->isHTMLElement()) formElement = static_cast<HTMLElement*>(m_node)->form(); v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node); v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement); v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0); v8::Handle<v8::Value> parameters[4] = { nodeWrapper, formWrapper, documentWrapper, v8::Handle<v8::Value>(v8::Null()) }; // FIXME: Remove this code when we stop doing the 'with' hack above. v8::Local<v8::Value> innerValue; { V8RecursionScope::MicrotaskSuppression scope; innerValue = intermediateFunction->Call(v8Context->Global(), 3, parameters); } if (innerValue.IsEmpty() || !innerValue->IsFunction()) return; v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); // Change the toString function on the wrapper function to avoid it // returning the source for the actual wrapper function. Instead it // returns source for a clean wrapper function with the event // argument wrapping the event source code. The reason for this is // that some web sites use toString on event functions and eval the // source returned (sometimes a RegExp is applied as well) for some // other use. That fails miserably if the actual wrapper source is // returned. v8::Persistent<v8::FunctionTemplate>& toStringTemplate = V8BindingPerIsolateData::current()->lazyEventListenerToStringTemplate(); if (toStringTemplate.IsEmpty()) toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8LazyEventListenerToString)); v8::Local<v8::Function> toStringFunction; if (!toStringTemplate.IsEmpty()) toStringFunction = toStringTemplate->GetFunction(); if (!toStringFunction.IsEmpty()) { String toStringResult = "function "; toStringResult.append(m_functionName); toStringResult.append("("); toStringResult.append(m_eventParameterName); toStringResult.append(") {\n "); toStringResult.append(m_code); toStringResult.append("\n}"); wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(), v8ExternalString(toStringResult)); wrappedFunction->Set(v8::String::NewSymbol("toString"), toStringFunction); } wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length())); // FIXME: Remove the following comment-outs. // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. // // For the time being, we comment out the following code since the // second parsing can happen. // // Since we only parse once, there's no need to keep data used for parsing around anymore. // m_functionName = String(); // m_code = String(); // m_eventParameterName = String(); // m_sourceURL = String(); setListenerObject(wrappedFunction); }