void reportException(ExecState* exec, JSValue exception) { if (exception.isObject() && asObject(exception)->exceptionType() == Terminated) return; UString errorMessage = exception.toString(exec); JSObject* exceptionObject = exception.toObject(exec); int lineNumber = exceptionObject->get(exec, Identifier(exec, "line")).toInt32(exec); UString exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL")).toString(exec); exec->clearException(); if (ExceptionBase* exceptionBase = toExceptionBase(exception)) errorMessage = stringToUString(exceptionBase->message() + ": " + exceptionBase->description()); ScriptExecutionContext* scriptExecutionContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); ASSERT(scriptExecutionContext); // Crash data indicates null-dereference crashes at this point in the Safari 4 Public Beta. // It's harmless to return here without reporting the exception to the log and the debugger in this case. if (!scriptExecutionContext) return; scriptExecutionContext->reportException(ustringToString(errorMessage), lineNumber, ustringToString(exceptionSourceURL), 0); }
bool NavigatorBeacon::canSendBeacon(ScriptExecutionContext& context, const URL& url, ExceptionCode& ec) { if (!url.isValid()) { ec = SYNTAX_ERR; return false; } // For now, only support HTTP and related. if (!url.protocolIsInHTTPFamily()) { ec = SECURITY_ERR; return false; } if (!context.contentSecurityPolicy()->allowConnectToSource(url, context.shouldBypassMainWorldContentSecurityPolicy())) { ec = SECURITY_ERR; return false; } // If detached from frame, do not allow sending a Beacon. if (!frame()) return false; return true; }
RefPtr<WebSocket> WebSocket::create(ScriptExecutionContext& context, const String& url, const Vector<String>& protocols, ExceptionCode& ec) { if (url.isNull()) { ec = SYNTAX_ERR; return nullptr; } RefPtr<WebSocket> webSocket(adoptRef(*new WebSocket(context))); webSocket->suspendIfNeeded(); webSocket->connect(context.completeURL(url), protocols, ec); if (ec) return nullptr; return WTF::move(webSocket); }
Command::ExecuteResult ChangeStaticCommand::execute(ScriptExecutionContext &scriptExecCtx) { Scene *const scene = scriptExecCtx.getGameData().getScene(_sceneId); if (!scene) { return Finished; } Static *const stat = scene->getStatic(_entityId); if (!stat) { return Finished; } switch (_register) { case AC: stat->_active = _value._byteVal; break; case NM: strncpy(stat->_name, _value._strVal, MAX_ENTITY_NAME_LENGTH); break; case XX: stat->_x = _value._wordVal; break; case YY: stat->_y = _value._byteVal; break; case XL: stat->_width = _value._wordVal; break; case YL: stat->_height = _value._byteVal; break; case WX: stat->_walkToX = _value._wordVal; break; case WY: stat->_walkToY = _value._byteVal; break; case SP: stat->_walkToFrame = _value._byteVal; break; default: warning("Object does not support changing this register."); break; } return Finished; }
RefPtr<FetchResponse> FetchResponse::redirect(ScriptExecutionContext& context, const String& url, int status, ExceptionCode& ec) { // FIXME: Tighten the URL parsing algorithm according https://url.spec.whatwg.org/#concept-url-parser. URL requestURL = context.completeURL(url); if (!requestURL.isValid() || !requestURL.user().isEmpty() || !requestURL.pass().isEmpty()) { ec = TypeError; return nullptr; } if (!isRedirectStatus(status)) { ec = TypeError; return nullptr; } auto redirectResponse = adoptRef(*new FetchResponse(context, { }, FetchHeaders::create(FetchHeaders::Guard::Immutable), { })); redirectResponse->m_response.setHTTPStatusCode(status); redirectResponse->m_headers->fastSet(HTTPHeaderName::Location, requestURL.string()); return WTFMove(redirectResponse); }
RefPtr<IDBRequest> IDBObjectStore::modernDelete(ScriptExecutionContext& context, JSValue key, ExceptionCodeWithMessage& ec) { auto exec = context.execState(); if (!exec) { ec.code = IDBDatabaseException::UnknownError; ec.message = ASCIILiteral("Failed to execute 'delete' on 'IDBObjectStore': Script execution context does not have an execution state."); return nullptr; } Ref<IDBKey> idbKey = scriptValueToIDBKey(*exec, key); if (!idbKey->isValid()) { ec.code = IDBDatabaseException::DataError; ec.message = ASCIILiteral("Failed to execute 'delete' on 'IDBObjectStore': The parameter is not a valid key."); return nullptr; } return doDelete(context, &IDBKeyRange::create(WTFMove(idbKey)).get(), ec); }
PassRefPtr<OfflineAudioContext> OfflineAudioContext::create(ScriptExecutionContext& context, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode& ec) { // FIXME: add support for workers. if (!context.isDocument()) { ec = NOT_SUPPORTED_ERR; return nullptr; } Document& document = toDocument(context); if (numberOfChannels > 10 || !isSampleRateRangeGood(sampleRate)) { ec = SYNTAX_ERR; return nullptr; } RefPtr<OfflineAudioContext> audioContext(adoptRef(new OfflineAudioContext(document, numberOfChannels, numberOfFrames, sampleRate))); audioContext->suspendIfNeeded(); return audioContext.release(); }
RefPtr<IDBRequest> IDBObjectStore::count(ScriptExecutionContext& context, JSValue key, ExceptionCodeWithMessage& ec) { LOG(IndexedDB, "IDBObjectStore::count"); auto exec = context.execState(); if (!exec) { ec.code = IDBDatabaseException::UnknownError; ec.message = ASCIILiteral("Failed to execute 'count' on 'IDBObjectStore': Script execution context does not have an execution state."); return nullptr; } Ref<IDBKey> idbKey = scriptValueToIDBKey(*exec, key); if (!idbKey->isValid()) { ec.code = IDBDatabaseException::DataError; ec.message = ASCIILiteral("Failed to execute 'count' on 'IDBObjectStore': The parameter is not a valid key."); return nullptr; } return doCount(context, IDBKeyRangeData(idbKey.ptr()), ec); }
PassRefPtr<Notification> Notification::create(ScriptExecutionContext& context, const String& title, const Dictionary& options) { RefPtr<Notification> notification(adoptRef(new Notification(context, title))); String argument; if (options.get("body", argument)) notification->setBody(argument); if (options.get("tag", argument)) notification->setTag(argument); if (options.get("lang", argument)) notification->setLang(argument); if (options.get("dir", argument)) notification->setDir(argument); if (options.get("icon", argument)) { URL iconURI = argument.isEmpty() ? URL() : context.completeURL(argument); if (!iconURI.isEmpty() && iconURI.isValid()) notification->setIconURL(iconURI); } notification->suspendIfNeeded(); return notification.release(); }
Command::ExecuteResult ChangeSceneCommand::execute(ScriptExecutionContext &scriptExecCtx) { Scene *const scene = scriptExecCtx.getGameData().getScene(_sceneId); if (!scene) { return Finished; } switch (_register) { case DS: scene->_startup = _value._byteVal; break; case DL: scene->_delay = _value._byteVal; break; case ND: scene->_noDoors = _value._byteVal; break; case NO: scene->_noObjects = _value._byteVal; break; case NS: scene->_noStatics = _value._byteVal; break; case PF: scene->_palRotFirst = _value._byteVal; break; case PL: scene->_palRotLast = _value._byteVal; break; case PD: scene->_palRotDelay = _value._byteVal; break; default: warning("Scene does not support changing this register."); break; } return Finished; }
RefPtr<Worker> Worker::create(ScriptExecutionContext& context, const String& url, ExceptionCode& ec) { ASSERT(isMainThread()); // We don't currently support nested workers, so workers can only be created from documents. ASSERT_WITH_SECURITY_IMPLICATION(context.isDocument()); Ref<Worker> worker = adoptRef(*new Worker(context)); worker->suspendIfNeeded(); URL scriptURL = worker->resolveURL(url, ec); if (scriptURL.isEmpty()) return nullptr; // The worker context does not exist while loading, so we must ensure that the worker object is not collected, nor are its event listeners. worker->setPendingActivity(worker.ptr()); worker->m_scriptLoader = WorkerScriptLoader::create(); worker->m_scriptLoader->loadAsynchronously(&context, scriptURL, DenyCrossOriginRequests, worker.ptr()); return WTF::move(worker); }
void ThreadableWebSocketChannelClientWrapper::processPendingTasksCallback(ScriptExecutionContext& context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper) { ASSERT_UNUSED(context, context.isWorkerGlobalScope()); wrapper->processPendingTasks(); }
void DOMTimer::fired() { // Retain this - if the timer is cancelled while this function is on the stack (implicitly and always // for one-shot timers, or if removeById is called on itself from within an interval timer fire) then // wait unit the end of this function to delete DOMTimer. RefPtr<DOMTimer> reference = this; ScriptExecutionContext* context = scriptExecutionContext(); ASSERT(context); DOMTimerFireState fireState(context); #if PLATFORM(IOS) Document* document = nullptr; if (context->isDocument()) { document = toDocument(context); ASSERT(!document->frame()->timersPaused()); } #endif context->setTimerNestingLevel(std::min(m_nestingLevel + 1, maxTimerNestingLevel)); ASSERT(!isSuspended()); ASSERT(!context->activeDOMObjectsAreSuspended()); UserGestureIndicator gestureIndicator(m_shouldForwardUserGesture ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture); // Only the first execution of a multi-shot timer should get an affirmative user gesture indicator. m_shouldForwardUserGesture = false; InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutId); // Simple case for non-one-shot timers. if (isActive()) { if (m_nestingLevel < maxTimerNestingLevel) { m_nestingLevel++; updateTimerIntervalIfNecessary(); } m_action->execute(context); InspectorInstrumentation::didFireTimer(cookie); if (fireState.scriptDidInteractWithUserObservablePlugin && m_throttleState != ShouldNotThrottle) { m_throttleState = ShouldNotThrottle; updateTimerIntervalIfNecessary(); } else if (fireState.scriptDidInteractWithNonUserObservablePlugin && m_throttleState == Undetermined) { m_throttleState = ShouldThrottle; updateTimerIntervalIfNecessary(); } return; } context->removeTimeout(m_timeoutId); #if PLATFORM(IOS) bool shouldReportLackOfChanges; bool shouldBeginObservingChanges; if (document) { shouldReportLackOfChanges = WebThreadCountOfObservedContentModifiers() == 1; shouldBeginObservingChanges = WebThreadContainsObservedContentModifier(this); } else { shouldReportLackOfChanges = false; shouldBeginObservingChanges = false; } if (shouldBeginObservingChanges) { WKBeginObservingContentChanges(false); WebThreadRemoveObservedContentModifier(this); } #endif m_action->execute(context); #if PLATFORM(IOS) if (shouldBeginObservingChanges) { WKStopObservingContentChanges(); if (WKObservedContentChange() == WKContentVisibilityChange || shouldReportLackOfChanges) if (document && document->page()) document->page()->chrome().client().observedContentChange(document->frame()); } #endif InspectorInstrumentation::didFireTimer(cookie); context->setTimerNestingLevel(0); }
EncodedJSValue JSC_HOST_CALL constructJSAudioContext(ExecState* exec) { DOMConstructorObject* jsConstructor = jsCast<DOMConstructorObject*>(exec->callee()); if (!jsConstructor) return throwVMError(exec, createReferenceError(exec, "AudioContext constructor callee is unavailable")); ScriptExecutionContext* scriptExecutionContext = jsConstructor->scriptExecutionContext(); if (!scriptExecutionContext) return throwVMError(exec, createReferenceError(exec, "AudioContext constructor script execution context is unavailable")); if (!scriptExecutionContext->isDocument()) return throwVMError(exec, createReferenceError(exec, "AudioContext constructor called in a script execution context which is not a document")); Document& document = toDocument(*scriptExecutionContext); RefPtr<AudioContext> audioContext; if (!exec->argumentCount()) { // Constructor for default AudioContext which talks to audio hardware. ExceptionCode ec = 0; audioContext = AudioContext::create(document, ec); if (ec) { setDOMException(exec, ec); return JSValue::encode(JSValue()); } if (!audioContext.get()) return throwVMError(exec, createSyntaxError(exec, "audio resources unavailable for AudioContext construction")); } else { #if ENABLE(LEGACY_WEB_AUDIO) // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer. // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate); document.addConsoleMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("Deprecated AudioContext constructor: use OfflineAudioContext instead")); if (exec->argumentCount() < 3) return throwVMError(exec, createNotEnoughArgumentsError(exec)); int32_t numberOfChannels = exec->argument(0).toInt32(exec); int32_t numberOfFrames = exec->argument(1).toInt32(exec); float sampleRate = exec->argument(2).toFloat(exec); if (numberOfChannels <= 0 || numberOfChannels > 10) return throwVMError(exec, createSyntaxError(exec, "Invalid number of channels")); if (numberOfFrames <= 0) return throwVMError(exec, createSyntaxError(exec, "Invalid number of frames")); if (sampleRate <= 0) return throwVMError(exec, createSyntaxError(exec, "Invalid sample rate")); ExceptionCode ec = 0; audioContext = OfflineAudioContext::create(document, numberOfChannels, numberOfFrames, sampleRate, ec); if (ec) { setDOMException(exec, ec); return throwVMError(exec, createSyntaxError(exec, "Error creating OfflineAudioContext")); } #else return throwVMError(exec, createSyntaxError(exec, "Illegal AudioContext constructor")); #endif } if (!audioContext.get()) return throwVMError(exec, createReferenceError(exec, "Error creating AudioContext")); return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), AudioContext, audioContext.get())); }
v8::Handle<v8::Value> V8WebSocket::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebSocket.Constructor"); if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError); if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) return args.Holder(); if (args.Length() == 0) return throwError("Not enough arguments", V8Proxy::SyntaxError); v8::TryCatch tryCatch; v8::Handle<v8::String> urlstring = args[0]->ToString(); if (tryCatch.HasCaught()) return throwError(tryCatch.Exception()); if (urlstring.IsEmpty()) return throwError("Empty URL", V8Proxy::SyntaxError); // Get the script execution context. ScriptExecutionContext* context = getScriptExecutionContext(); if (!context) return throwError("WebSocket constructor's associated frame is not available", V8Proxy::ReferenceError); const KURL& url = context->completeURL(toWebCoreString(urlstring)); RefPtr<WebSocket> webSocket = WebSocket::create(context); ExceptionCode ec = 0; if (args.Length() < 2) webSocket->connect(url, ec); else { v8::Local<v8::Value> protocolsValue = args[1]; if (protocolsValue->IsArray()) { Vector<String> protocols; v8::Local<v8::Array> protocolsArray = v8::Local<v8::Array>::Cast(protocolsValue); for (uint32_t i = 0; i < protocolsArray->Length(); ++i) { v8::TryCatch tryCatchProtocol; v8::Handle<v8::String> protocol = protocolsArray->Get(v8::Int32::New(i))->ToString(); if (tryCatchProtocol.HasCaught()) return throwError(tryCatchProtocol.Exception()); protocols.append(toWebCoreString(protocol)); } webSocket->connect(url, protocols, ec); } else { v8::TryCatch tryCatchProtocol; v8::Handle<v8::String> protocol = protocolsValue->ToString(); if (tryCatchProtocol.HasCaught()) return throwError(tryCatchProtocol.Exception()); webSocket->connect(url, toWebCoreString(protocol), ec); } } if (ec) return throwError(ec); // Setup the standard wrapper object internal fields. V8DOMWrapper::setDOMWrapper(args.Holder(), &info, webSocket.get()); // Add object to the wrapper map. webSocket->ref(); V8DOMWrapper::setJSWrapperForActiveDOMObject(webSocket.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); }
bool DatabaseManager::hasOpenDatabases(ScriptExecutionContext& context) { auto databaseContext = context.databaseContext(); return databaseContext && databaseContext->hasOpenDatabases(); }
Document* NotificationCenter::document() const { ScriptExecutionContext* context = scriptExecutionContext(); return context->isDocument() ? static_cast<Document*>(context) : 0; }
void WorkerDebuggerAgent::addConsoleMessage(MessageSource source, MessageLevel level, const String& message, const String& sourceURL) { ScriptExecutionContext* context = m_inspectedWorkerGlobalScope; context->addConsoleMessage(source, level, message, sourceURL, 0); }
bool ActiveDOMCallback::canInvokeCallback() const { ScriptExecutionContext* context = scriptExecutionContext(); return context && !context->activeDOMObjectsAreSuspended() && !context->activeDOMObjectsAreStopped(); }
void DOMTimer::fired() { ScriptExecutionContext* context = scriptExecutionContext(); ASSERT(context); #if PLATFORM(IOS) Document* document = nullptr; if (!context->isDocument()) { document = toDocument(context); ASSERT(!document->frame()->timersPaused()); } #endif timerNestingLevel = m_nestingLevel; ASSERT(!isSuspended()); ASSERT(!context->activeDOMObjectsAreSuspended()); UserGestureIndicator gestureIndicator(m_shouldForwardUserGesture ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture); // Only the first execution of a multi-shot timer should get an affirmative user gesture indicator. m_shouldForwardUserGesture = false; InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutId); // Simple case for non-one-shot timers. if (isActive()) { double minimumInterval = context->minimumTimerInterval(); if (repeatInterval() && repeatInterval() < minimumInterval) { m_nestingLevel++; if (m_nestingLevel >= maxTimerNestingLevel) augmentRepeatInterval(minimumInterval - repeatInterval()); } // No access to member variables after this point, it can delete the timer. m_action->execute(context); InspectorInstrumentation::didFireTimer(cookie); return; } // Delete timer before executing the action for one-shot timers. OwnPtr<ScheduledAction> action = m_action.release(); // No access to member variables after this point. delete this; #if PLATFORM(IOS) bool shouldReportLackOfChanges; bool shouldBeginObservingChanges; if (document) { shouldReportLackOfChanges = WebThreadCountOfObservedContentModifiers() == 1; shouldBeginObservingChanges = WebThreadContainsObservedContentModifier(this); } else { shouldReportLackOfChanges = false; shouldBeginObservingChanges = false; } if (shouldBeginObservingChanges) { WKBeginObservingContentChanges(false); WebThreadRemoveObservedContentModifier(this); } #endif action->execute(context); #if PLATFORM(IOS) if (shouldBeginObservingChanges) { WKStopObservingContentChanges(); if (WKObservedContentChange() == WKContentVisibilityChange || shouldReportLackOfChanges) if (document && document->page()) document->page()->chrome().client().observedContentChange(document->frame()); } #endif InspectorInstrumentation::didFireTimer(cookie); timerNestingLevel = 0; }
static void logOpenDatabaseError(ScriptExecutionContext& context, const String& name) { LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.utf8().data(), context.securityOrigin()->toString().utf8().data()); }
void DatabaseManager::logErrorMessage(ScriptExecutionContext& context, const String& message) { context.addConsoleMessage(MessageSource::Storage, MessageLevel::Error, message); }
void JSEventListener::handleEvent(Event* event, bool isWindowEvent) { JSLock lock(SilenceAssertionsOnly); JSObject* jsFunction = this->jsFunction(); if (!jsFunction) return; JSDOMGlobalObject* globalObject = m_globalObject; // Null check as clearGlobalObject() can clear this and we still get called back by // xmlhttprequest objects. See http://bugs.webkit.org/show_bug.cgi?id=13275 // FIXME: Is this check still necessary? Requests are supposed to be stopped before clearGlobalObject() is called. ASSERT(globalObject); if (!globalObject) return; ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext(); if (!scriptExecutionContext) return; if (scriptExecutionContext->isDocument()) { JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject); Frame* frame = window->impl()->frame(); if (!frame) return; // The window must still be active in its frame. See <https://bugs.webkit.org/show_bug.cgi?id=21921>. // FIXME: A better fix for this may be to change DOMWindow::frame() to not return a frame the detached window used to be in. if (frame->domWindow() != window->impl()) return; // FIXME: Is this check needed for other contexts? ScriptController* script = frame->script(); if (!script->isEnabled() || script->isPaused()) return; } ExecState* exec = globalObject->globalExec(); JSValue handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent")); CallData callData; CallType callType = handleEventFunction.getCallData(callData); if (callType == CallTypeNone) { handleEventFunction = JSValue(); callType = jsFunction->getCallData(callData); } if (callType != CallTypeNone) { ref(); MarkedArgumentBuffer args; args.append(toJS(exec, globalObject, event)); Event* savedEvent = globalObject->currentEvent(); globalObject->setCurrentEvent(event); // If this event handler is the first JavaScript to execute, then the // dynamic global object should be set to the global object of the // window in which the event occurred. JSGlobalData* globalData = globalObject->globalData(); DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject); JSValue retval; if (handleEventFunction) { globalObject->globalData()->timeoutChecker.start(); retval = call(exec, handleEventFunction, callType, callData, jsFunction, args); } else { JSValue thisValue; if (isWindowEvent) thisValue = globalObject->toThisObject(exec); else thisValue = toJS(exec, globalObject, event->currentTarget()); globalObject->globalData()->timeoutChecker.start(); retval = call(exec, jsFunction, callType, callData, thisValue, args); } globalObject->globalData()->timeoutChecker.stop(); globalObject->setCurrentEvent(savedEvent); if (exec->hadException()) reportCurrentException(exec); else { if (!retval.isUndefinedOrNull() && event->storesResultAsString()) event->storeResult(retval.toString(exec)); if (m_isAttribute) { bool retvalbool; if (retval.getBoolean(retvalbool) && !retvalbool) event->preventDefault(); } } if (scriptExecutionContext->isDocument()) Document::updateStyleForAllDocuments(); deref(); } }
Command::ExecuteResult PlayAnimationCommand::execute(ScriptExecutionContext &scriptExecCtx) { scriptExecCtx.getGame().getRoom().drawFrames(_fromFrame - 1, _toFrame - 1); return Finished; }
Ref<DatabaseContext> DatabaseManager::databaseContext(ScriptExecutionContext& context) { if (auto databaseContext = context.databaseContext()) return *databaseContext; return adoptRef(*new DatabaseContext(context)); }