TEST_F(ScriptPromiseTest, castNonPromise) { String onFulfilled1, onFulfilled2, onRejected1, onRejected2; ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello")); ScriptPromise promise1 = ScriptPromise::cast(scriptState(), ScriptValue(value)); ScriptPromise promise2 = ScriptPromise::cast(scriptState(), ScriptValue(value)); promise1.then(Function::create(isolate(), &onFulfilled1), Function::create(isolate(), &onRejected1)); promise2.then(Function::create(isolate(), &onFulfilled2), Function::create(isolate(), &onRejected2)); ASSERT_FALSE(promise1.isEmpty()); ASSERT_FALSE(promise2.isEmpty()); EXPECT_NE(promise1.v8Value(), promise2.v8Value()); ASSERT_TRUE(promise1.v8Value()->IsPromise()); ASSERT_TRUE(promise2.v8Value()->IsPromise()); EXPECT_EQ(String(), onFulfilled1); EXPECT_EQ(String(), onFulfilled2); EXPECT_EQ(String(), onRejected1); EXPECT_EQ(String(), onRejected2); isolate()->RunMicrotasks(); EXPECT_EQ("hello", onFulfilled1); EXPECT_EQ("hello", onFulfilled2); EXPECT_EQ(String(), onRejected1); EXPECT_EQ(String(), onRejected2); }
v8::Local<v8::Value> V8WorkerGlobalScopeEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { v8::Local<v8::Function> handlerFunction = getListenerFunction(scriptState()->executionContext()); v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FunctionCall", "data", devToolsTraceEventData(scriptState()->executionContext(), handlerFunction, isolate())); TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie; if (InspectorInstrumentation::timelineAgentEnabled(scriptState()->executionContext())) { int scriptId = 0; String resourceName; int lineNumber = 1; GetDevToolsFunctionInfo(handlerFunction, isolate(), scriptId, resourceName, lineNumber); cookie = InspectorInstrumentation::willCallFunction(scriptState()->executionContext(), scriptId, resourceName, lineNumber); } v8::Handle<v8::Value> parameters[1] = { jsEvent }; v8::Local<v8::Value> result = V8ScriptRunner::callFunction(handlerFunction, scriptState()->executionContext(), receiver, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); InspectorInstrumentation::didCallFunction(cookie); TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); return result; }
v8::Local<v8::Value> V8ErrorHandler::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { if (!event->hasInterface(EventNames::ErrorEvent)) return V8EventListener::callListenerFunction(jsEvent, event); ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); if (errorEvent->world() && errorEvent->world() != &world()) return v8::Null(isolate()); v8::Local<v8::Object> listener = getListenerObject(scriptState()->executionContext()); v8::Local<v8::Value> returnValue; if (!listener.IsEmpty() && listener->IsFunction()) { v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); v8::Local<v8::Object> thisValue = scriptState()->context()->Global(); v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(isolate(), jsEvent->ToObject(), V8HiddenValue::error(isolate())); if (error.IsEmpty()) error = v8::Null(isolate()); v8::Handle<v8::Value> parameters[5] = { v8String(isolate(), errorEvent->message()), v8String(isolate(), errorEvent->filename()), v8::Integer::New(isolate(), errorEvent->lineno()), v8::Integer::New(isolate(), errorEvent->colno()), error }; v8::TryCatch tryCatch; tryCatch.SetVerbose(true); returnValue = ScriptController::callFunction(scriptState()->executionContext(), callFunction, thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); } return returnValue; }
TEST_F(ScriptPromiseTest, castPromise) { ScriptPromise promise = ScriptPromiseResolver::create(scriptState())->promise(); ScriptPromise newPromise = ScriptPromise::cast(scriptState(), promise.v8Value()); ASSERT_FALSE(promise.isEmpty()); EXPECT_EQ(promise.v8Value(), newPromise.v8Value()); }
void ConsoleMessage::frameWindowDiscarded(LocalDOMWindow* window) { if (scriptState() && scriptState()->domWindow() == window) setScriptState(nullptr); if (!m_scriptArguments) return; if (m_scriptArguments->scriptState()->domWindow() != window) return; if (!m_message) m_message = "<message collected>"; m_scriptArguments.clear(); }
v8::Local<v8::Object> V8WorkerGlobalScopeEventListener::getReceiverObject(Event* event) { v8::Local<v8::Object> listener = getListenerObject(scriptState()->executionContext()); if (!listener.IsEmpty() && !listener->IsFunction()) return listener; EventTarget* target = event->currentTarget(); v8::Handle<v8::Value> value = toV8(target, scriptState()->context()->Global(), isolate()); if (value.IsEmpty()) return v8::Local<v8::Object>(); return v8::Local<v8::Object>::New(isolate(), v8::Handle<v8::Object>::Cast(value)); }
bool SerializedScriptValueReaderForModules::readDOMFileSystem(v8::Local<v8::Value>* value) { uint32_t type; String name; String url; if (!doReadUint32(&type)) return false; if (!readWebCoreString(&name)) return false; if (!readWebCoreString(&url)) return false; DOMFileSystem* fs = DOMFileSystem::create(scriptState()->executionContext(), name, static_cast<FileSystemType>(type), KURL(ParsedURLString, url)); *value = toV8(fs, scriptState()->context()->Global(), isolate()); return true; }
void IDBOpenDBRequest::onUpgradeNeeded(int64_t oldVersion, PassOwnPtr<WebIDBDatabase> backend, const IDBDatabaseMetadata& metadata, WebIDBDataLoss dataLoss, String dataLossMessage) { IDB_TRACE("IDBOpenDBRequest::onUpgradeNeeded()"); if (m_contextStopped || !executionContext()) { OwnPtr<WebIDBDatabase> db = backend; db->abort(m_transactionId); db->close(); return; } if (!shouldEnqueueEvent()) return; ASSERT(m_databaseCallbacks); IDBDatabase* idbDatabase = IDBDatabase::create(executionContext(), backend, m_databaseCallbacks.release()); idbDatabase->setMetadata(metadata); if (oldVersion == IDBDatabaseMetadata::NoIntVersion) { // This database hasn't had an integer version before. oldVersion = IDBDatabaseMetadata::DefaultIntVersion; } IDBDatabaseMetadata oldMetadata(metadata); oldMetadata.intVersion = oldVersion; m_transaction = IDBTransaction::create(scriptState(), m_transactionId, idbDatabase, this, oldMetadata); setResult(IDBAny::create(idbDatabase)); if (m_version == IDBDatabaseMetadata::NoIntVersion) m_version = 1; enqueueEvent(IDBVersionChangeEvent::create(EventTypeNames::upgradeneeded, oldVersion, m_version, dataLoss, dataLossMessage)); }
void IDBRequest::setBlobInfo(PassOwnPtr<Vector<WebBlobInfo>> blobInfo) { ASSERT(!m_blobInfo); m_blobInfo = blobInfo; if (m_blobInfo && m_blobInfo->size() > 0) V8PerIsolateData::from(scriptState()->isolate())->ensureIDBPendingTransactionMonitor()->registerRequest(*this); }
TEST_F(ScriptPromiseTest, constructFromNonPromise) { v8::TryCatch trycatch; ScriptPromise promise(scriptState(), v8::Undefined(isolate())); ASSERT_TRUE(trycatch.HasCaught()); ASSERT_TRUE(promise.isEmpty()); }
void InspectorFrontend::pausedScript(SerializedScriptValue* callFrames) { ScriptValue callFramesValue = ScriptValue::deserialize(scriptState(), callFrames); ScriptFunctionCall function(m_webInspector, "dispatch"); function.appendArgument("pausedScript"); function.appendArgument(callFramesValue); function.call(); }
void IDBRequest::handleBlobAcks() { if (m_blobInfo.get() && m_blobInfo->size()) { m_transaction->db()->ackReceivedBlobs(m_blobInfo.get()); m_blobInfo.clear(); V8PerIsolateData::from(scriptState()->isolate())->ensureIDBPendingTransactionMonitor()->unregisterRequest(*this); } }
v8::Local<v8::Value> V8EventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { v8::Local<v8::Function> handlerFunction = getListenerFunction(scriptState()->executionContext()); v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); if (!scriptState()->executionContext()->isDocument()) return v8::Local<v8::Value>(); LocalFrame* frame = toDocument(scriptState()->executionContext())->frame(); if (!frame) return v8::Local<v8::Value>(); v8::Handle<v8::Value> parameters[1] = { jsEvent }; return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LENGTH(parameters), parameters); }
bool SerializedScriptValueReaderForModules::readCryptoKey(v8::Local<v8::Value>* value) { uint32_t rawKeyType; if (!doReadUint32(&rawKeyType)) return false; WebCryptoKeyAlgorithm algorithm; WebCryptoKeyType type = WebCryptoKeyTypeSecret; switch (static_cast<CryptoKeySubTag>(rawKeyType)) { case AesKeyTag: if (!doReadAesKey(algorithm, type)) return false; break; case HmacKeyTag: if (!doReadHmacKey(algorithm, type)) return false; break; case RsaHashedKeyTag: if (!doReadRsaHashedKey(algorithm, type)) return false; break; case EcKeyTag: if (!doReadEcKey(algorithm, type)) return false; break; case NoParamsKeyTag: if (!doReadKeyWithoutParams(algorithm, type)) return false; break; default: return false; } WebCryptoKeyUsageMask usages; bool extractable; if (!doReadKeyUsages(usages, extractable)) return false; uint32_t keyDataLength; if (!doReadUint32(&keyDataLength)) return false; if (position() + keyDataLength > length()) return false; const uint8_t* keyData = allocate(keyDataLength); WebCryptoKey key = WebCryptoKey::createNull(); if (!Platform::current()->crypto()->deserializeKeyForClone( algorithm, type, extractable, usages, keyData, keyDataLength, key)) { return false; } *value = toV8(CryptoKey::create(key), scriptState()->context()->Global(), isolate()); return true; }
void V8WorkerGlobalScopeEventListener::handleEvent(ExecutionContext*, Event* event) { // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. // See issue 889829. RefPtr<V8AbstractEventListener> protect(this); WorkerScriptController* script = toWorkerGlobalScope(scriptState()->executionContext())->script(); if (!script) return; if (scriptState()->contextIsValid()) return; ScriptState::Scope scope(scriptState()); // Get the V8 wrapper for the event object. v8::Handle<v8::Value> jsEvent = toV8(event, scriptState()->context()->Global(), isolate()); invokeEventHandler(event, v8::Local<v8::Value>::New(isolate(), jsEvent)); }
TEST_F(ScriptPromiseTest, reject) { String onFulfilled, onRejected; ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello")); ScriptPromise promise = ScriptPromise::reject(scriptState(), ScriptValue(value)); promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); ASSERT_FALSE(promise.isEmpty()); ASSERT_TRUE(promise.v8Value()->IsPromise()); EXPECT_EQ(String(), onFulfilled); EXPECT_EQ(String(), onRejected); isolate()->RunMicrotasks(); EXPECT_EQ(String(), onFulfilled); EXPECT_EQ("hello", onRejected); }
v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event) { v8::Local<v8::Object> listener = m_listener.newLocal(isolate()); if (!m_listener.isEmpty() && !listener->IsFunction()) return listener; EventTarget* target = event->currentTarget(); v8::Handle<v8::Value> value = toV8(target, scriptState()->context()->Global(), isolate()); if (value.IsEmpty()) return v8::Local<v8::Object>(); return v8::Local<v8::Object>::New(isolate(), v8::Handle<v8::Object>::Cast(value)); }
PassRefPtr<Array<CallFrame> > InjectedScript::wrapCallFrames(const ScriptValue& callFrames) { ASSERT(!hasNoValue()); ScriptFunctionCall function(injectedScriptObject(), "wrapCallFrames"); function.appendArgument(callFrames); bool hadException = false; ScriptValue callFramesValue = callFunctionWithEvalEnabled(function, hadException); ASSERT(!hadException); RefPtr<InspectorValue> result = callFramesValue.toInspectorValue(scriptState()); if (result->type() == InspectorValue::TypeArray) return Array<CallFrame>::runtimeCast(result); return Array<CallFrame>::create(); }
void V8AbstractEventListener::handleEvent(ExecutionContext*, Event* event) { // Don't reenter V8 if execution was terminated in this instance of V8. if (scriptState()->executionContext()->isJSExecutionForbidden()) return; ASSERT(event); // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. // See issue 889829. RefPtr<V8AbstractEventListener> protect(this); if (scriptState()->contextIsEmpty()) return; ScriptState::Scope scope(scriptState()); // Get the V8 wrapper for the event object. v8::Handle<v8::Value> jsEvent = toV8(event, scriptState()->context()->Global(), isolate()); if (jsEvent.IsEmpty()) return; invokeEventHandler(event, v8::Local<v8::Value>::New(isolate(), jsEvent)); }
void InspectorFrontend::didEditScriptSource(long callId, bool success, const String& result, SerializedScriptValue* newCallFrames) { ScriptFunctionCall function(m_webInspector, "dispatch"); function.appendArgument("didEditScriptSource"); function.appendArgument(callId); function.appendArgument(success); function.appendArgument(result); if (success && newCallFrames) { ScriptValue newCallFramesValue = ScriptValue::deserialize(scriptState(), newCallFrames); ASSERT(!newCallFramesValue .hasNoValue()); function.appendArgument(newCallFramesValue); } function.call(); }
void InspectorFrontend::didDispatchOnInjectedScript(long callId, SerializedScriptValue* result, bool isException) { ScriptFunctionCall function(m_webInspector, "dispatch"); function.appendArgument("didDispatchOnInjectedScript"); function.appendArgument(callId); if (isException) function.appendArgument(""); else { ScriptValue resultValue = ScriptValue::deserialize(scriptState(), result); function.appendArgument(resultValue); } function.appendArgument(isException); function.call(); }
Node* InjectedScript::nodeForObjectId(const String& objectId) { if (isEmpty() || !canAccessInspectedWindow()) return 0; ScriptFunctionCall function(injectedScriptObject(), "nodeForObjectId"); function.appendArgument(objectId); bool hadException = false; ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException); ASSERT(!hadException); return InjectedScriptHost::scriptValueAsNode(scriptState(), resultValue); }
void V8AbstractEventListener::invokeEventHandler(Event* event, v8::Local<v8::Value> jsEvent) { // If jsEvent is empty, attempt to set it as a hidden value would crash v8. if (jsEvent.IsEmpty()) return; ASSERT(!scriptState()->contextIsEmpty()); v8::Local<v8::Value> returnValue; { // Catch exceptions thrown in the event handler so they do not propagate to javascript code that caused the event to fire. v8::TryCatch tryCatch; tryCatch.SetVerbose(true); // Save the old 'event' property so we can restore it later. v8::Local<v8::Value> savedEvent = V8HiddenValue::getHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate())); tryCatch.Reset(); // Make the event available in the global object, so LocalDOMWindow can expose it. V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate()), jsEvent); tryCatch.Reset(); returnValue = callListenerFunction(jsEvent, event); if (tryCatch.HasCaught()) event->target()->uncaughtExceptionInEventHandler(); if (!tryCatch.CanContinue()) { // Result of TerminateExecution(). if (scriptState()->executionContext()->isWorkerGlobalScope()) toWorkerGlobalScope(scriptState()->executionContext())->script()->forbidExecution(); return; } tryCatch.Reset(); // Restore the old event. This must be done for all exit paths through this method. if (savedEvent.IsEmpty()) V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate()), v8::Undefined(isolate())); else V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate()), savedEvent); tryCatch.Reset(); } if (returnValue.IsEmpty()) return; if (m_isAttribute && !returnValue->IsNull() && !returnValue->IsUndefined() && event->isBeforeUnloadEvent()) { TOSTRING_VOID(V8StringResource<>, stringReturnValue, returnValue); toBeforeUnloadEvent(event)->setReturnValue(stringReturnValue); } if (m_isAttribute && shouldPreventDefault(returnValue)) event->preventDefault(); }
PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapObject(const ScriptValue& value, const String& groupName, bool generatePreview) const { ASSERT(!isEmpty()); ScriptFunctionCall wrapFunction(injectedScriptObject(), "wrapObject"); wrapFunction.appendArgument(value); wrapFunction.appendArgument(groupName); wrapFunction.appendArgument(canAccessInspectedWindow()); wrapFunction.appendArgument(generatePreview); bool hadException = false; ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); if (hadException) return nullptr; RefPtr<JSONObject> rawResult = r.toJSONValue(scriptState())->asObject(); return TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult); }
PassRefPtr<Array<Inspector::TypeBuilder::Debugger::CallFrame>> InjectedScript::wrapCallFrames(const Deprecated::ScriptValue& callFrames) { ASSERT(!hasNoValue()); Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("wrapCallFrames"), inspectorEnvironment()->functionCallHandler()); function.appendArgument(callFrames); bool hadException = false; Deprecated::ScriptValue callFramesValue = callFunctionWithEvalEnabled(function, hadException); ASSERT(!hadException); RefPtr<InspectorValue> result = callFramesValue.toInspectorValue(scriptState()); if (result->type() == InspectorValue::TypeArray) return Array<Inspector::TypeBuilder::Debugger::CallFrame>::runtimeCast(result); return Array<Inspector::TypeBuilder::Debugger::CallFrame>::create(); }
TEST_F(ScriptPromiseTest, rejectWithExceptionState) { String onFulfilled, onRejected; ScriptPromise promise = ScriptPromise::rejectWithDOMException(scriptState(), DOMException::create(SyntaxError, "some syntax error")); promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); ASSERT_FALSE(promise.isEmpty()); EXPECT_EQ(String(), onFulfilled); EXPECT_EQ(String(), onRejected); isolate()->RunMicrotasks(); EXPECT_EQ(String(), onFulfilled); EXPECT_EQ("SyntaxError: some syntax error", onRejected); }
PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapTable(const ScriptValue& table, const ScriptValue& columns) const { ASSERT(!isEmpty()); ScriptFunctionCall wrapFunction(injectedScriptObject(), "wrapTable"); wrapFunction.appendArgument(canAccessInspectedWindow()); wrapFunction.appendArgument(table); if (columns.isEmpty()) wrapFunction.appendArgument(false); else wrapFunction.appendArgument(columns); bool hadException = false; ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); if (hadException) return nullptr; RefPtr<JSONObject> rawResult = r.toJSONValue(scriptState())->asObject(); return TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult); }
TEST_F(ScriptPromiseTest, rejectThen) { RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); ScriptPromise promise = resolver->promise(); String onFulfilled, onRejected; resolver->reject("hello"); promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); ASSERT_FALSE(promise.isEmpty()); EXPECT_EQ(String(), onFulfilled); EXPECT_EQ(String(), onRejected); isolate()->RunMicrotasks(); EXPECT_EQ(String(), onFulfilled); EXPECT_EQ("hello", onRejected); }
PassRefPtr<Inspector::TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapObject(const Deprecated::ScriptValue& value, const String& groupName, bool generatePreview) const { ASSERT(!hasNoValue()); Deprecated::ScriptFunctionCall wrapFunction(injectedScriptObject(), ASCIILiteral("wrapObject"), inspectorEnvironment()->functionCallHandler()); wrapFunction.appendArgument(value); wrapFunction.appendArgument(groupName); wrapFunction.appendArgument(hasAccessToInspectedScriptState()); wrapFunction.appendArgument(generatePreview); bool hadException = false; Deprecated::ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); if (hadException) return nullptr; RefPtr<InspectorObject> rawResult = r.toInspectorValue(scriptState())->asObject(); return Inspector::TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult); }
PassRefPtr<Inspector::TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapTable(const Deprecated::ScriptValue& table, const Deprecated::ScriptValue& columns) const { ASSERT(!hasNoValue()); Deprecated::ScriptFunctionCall wrapFunction(injectedScriptObject(), ASCIILiteral("wrapTable"), inspectorEnvironment()->functionCallHandler()); wrapFunction.appendArgument(hasAccessToInspectedScriptState()); wrapFunction.appendArgument(table); if (columns.hasNoValue()) wrapFunction.appendArgument(false); else wrapFunction.appendArgument(columns); bool hadException = false; Deprecated::ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); if (hadException) return nullptr; RefPtr<InspectorObject> rawResult = r.toInspectorValue(scriptState())->asObject(); return Inspector::TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult); }