JSValue JSCallbackData::invokeCallback(MarkedArgumentBuffer& args, bool* raisedException) { ASSERT(callback()); ASSERT(globalObject()); ExecState* exec = globalObject()->globalExec(); JSValue function = callback()->get(exec, Identifier(exec, "handleEvent")); CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) { callType = callback()->getCallData(callData); if (callType == CallTypeNone) return JSValue(); function = callback(); } globalObject()->globalData()->timeoutChecker.start(); JSValue result = globalObject()->scriptExecutionContext()->isDocument() ? JSMainThreadExecState::call(exec, function, callType, callData, callback(), args) : JSC::call(exec, function, callType, callData, callback(), args); globalObject()->globalData()->timeoutChecker.stop(); Document::updateStyleForAllDocuments(); if (exec->hadException()) { reportCurrentException(exec); if (raisedException) *raisedException = true; return result; } return result; }
JSValue* JSHTMLDocument::open(ExecState* exec, const ArgList& args) { // For compatibility with other browsers, pass open calls with more than 2 parameters to the window. if (args.size() > 2) { Frame* frame = static_cast<HTMLDocument*>(impl())->frame(); if (frame) { JSDOMWindowShell* wrapper = toJSDOMWindowShell(frame); if (wrapper) { JSValue* function = wrapper->get(exec, Identifier(exec, "open")); CallData callData; CallType callType = function->getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); return call(exec, function, callType, callData, wrapper, args); } } return jsUndefined(); } // document.open clobbers the security context of the document and // aliases it with the active security context. Document* activeDocument = asJSDOMWindow(exec->lexicalGlobalObject())->impl()->document(); // In the case of two parameters or fewer, do a normal document open. static_cast<HTMLDocument*>(impl())->open(activeDocument); return jsUndefined(); }
ScriptObject InjectedScriptHost::createInjectedScript(const String& source, ScriptState* scriptState, long id) { SourceCode sourceCode = makeSource(stringToUString(source)); JSLock lock(SilenceAssertionsOnly); JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); JSValue globalThisValue = scriptState->globalThisValue(); Completion comp = JSMainThreadExecState::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue); if (comp.complType() != JSC::Normal && comp.complType() != JSC::ReturnValue) return ScriptObject(); JSValue functionValue = comp.value(); CallData callData; CallType callType = functionValue.getCallData(callData); if (callType == CallTypeNone) return ScriptObject(); MarkedArgumentBuffer args; args.append(toJS(scriptState, globalObject, this)); args.append(globalThisValue); args.append(jsNumber(scriptState, id)); args.append(jsString(scriptState, String("JSC"))); JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args); if (result.isObject()) return ScriptObject(scriptState, result.getObject()); return ScriptObject(); }
JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { CallData callData; CallType callType = thisValue.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); JSValue array = args.at(1); MarkedArgumentBuffer applyArgs; if (!array.isUndefinedOrNull()) { if (!array.isObject()) return throwError(exec, TypeError); if (asObject(array)->classInfo() == &Arguments::info) asArguments(array)->fillArgList(exec, applyArgs); else if (isJSArray(&exec->globalData(), array)) asArray(array)->fillArgList(exec, applyArgs); else if (asObject(array)->inherits(&JSArray::info)) { unsigned length = asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned i = 0; i < length; ++i) applyArgs.append(asArray(array)->get(exec, i)); } else return throwError(exec, TypeError); } return call(exec, thisValue, callType, callData, args.at(0), applyArgs); }
void JSCustomPositionErrorCallback::handleEvent(PositionError* positionError) { ASSERT(m_callback); ASSERT(m_globalObject); ExecState* exec = m_globalObject->globalExec(); JSC::JSLock lock(SilenceAssertionsOnly); JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) { callType = m_callback->getCallData(callData); if (callType == CallTypeNone) { // FIXME: Should an exception be thrown here? return; } function = m_callback; } RefPtr<JSCustomPositionErrorCallback> protect(this); MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), positionError)); m_globalObject->globalData()->timeoutChecker.start(); call(exec, function, callType, callData, m_callback, args); m_globalObject->globalData()->timeoutChecker.stop(); if (exec->hadException()) reportCurrentException(exec); Document::updateStyleForAllDocuments(); }
bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLError* error) { ASSERT(m_callback); ASSERT(m_frame); if (!m_frame->script()->isEnabled()) return true; JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); KJS::JSLock lock; JSValue* handleEventFunction = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData handleEventCallData; CallType handleEventCallType = handleEventFunction->getCallData(handleEventCallData); CallData callbackCallData; CallType callbackCallType = CallTypeNone; if (handleEventCallType == CallTypeNone) { callbackCallType = m_callback->getCallData(callbackCallData); if (callbackCallType == CallTypeNone) { // FIXME: Should an exception be thrown here? return true; } } RefPtr<JSCustomSQLStatementErrorCallback> protect(this); ArgList args; args.append(toJS(exec, transaction)); args.append(toJS(exec, error)); JSValue* result; globalObject->startTimeoutCheck(); if (handleEventCallType != CallTypeNone) result = call(exec, handleEventFunction, handleEventCallType, handleEventCallData, m_callback, args); else result = call(exec, m_callback, callbackCallType, callbackCallData, m_callback, args); globalObject->stopTimeoutCheck(); if (exec->hadException()) { JSObject* exception = exec->exception()->toObject(exec); String message = exception->get(exec, exec->propertyNames().message)->toString(exec); int lineNumber = exception->get(exec, Identifier(exec, "line"))->toInt32(exec); String sourceURL = exception->get(exec, Identifier(exec, "sourceURL"))->toString(exec); m_frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, message, lineNumber, sourceURL); exec->clearException(); // The spec says: // "If the error callback returns false, then move on to the next statement..." // "Otherwise, the error callback did not return false, or there was no error callback" // Therefore an exception and returning true are the same thing - so, return true on an exception return true; } Document::updateDocumentsRendering(); return result->toBoolean(exec); }
bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLError* error) { ASSERT(m_callback); ASSERT(m_frame); if (!m_frame->script()->isEnabled()) return true; JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); JSC::JSLock lock(false); JSValue handleEventFunction = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData handleEventCallData; CallType handleEventCallType = handleEventFunction.getCallData(handleEventCallData); CallData callbackCallData; CallType callbackCallType = CallTypeNone; if (handleEventCallType == CallTypeNone) { callbackCallType = m_callback->getCallData(callbackCallData); if (callbackCallType == CallTypeNone) { // FIXME: Should an exception be thrown here? return true; } } RefPtr<JSCustomSQLStatementErrorCallback> protect(this); MarkedArgumentBuffer args; args.append(toJS(exec, transaction)); args.append(toJS(exec, error)); JSValue result; globalObject->globalData()->timeoutChecker.start(); if (handleEventCallType != CallTypeNone) result = call(exec, handleEventFunction, handleEventCallType, handleEventCallData, m_callback, args); else result = call(exec, m_callback, callbackCallType, callbackCallData, m_callback, args); globalObject->globalData()->timeoutChecker.stop(); if (exec->hadException()) { reportCurrentException(exec); // The spec says: // "If the error callback returns false, then move on to the next statement..." // "Otherwise, the error callback did not return false, or there was no error callback" // Therefore an exception and returning true are the same thing - so, return true on an exception return true; } Document::updateStyleForAllDocuments(); return result.toBoolean(exec); }
JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { CallData callData; CallType callType = thisValue.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); ArgList callArgs; args.getSlice(1, callArgs); return call(exec, thisValue, callType, callData, args.at(0), callArgs); }
ScheduledAction* ScheduledAction::create(ExecState* exec, const ArgList& args) { JSValue v = args.at(0); CallData callData; if (v.getCallData(callData) == CallTypeNone) { UString string = v.toString(exec); if (exec->hadException()) return 0; return new ScheduledAction(string); } ArgList argsTail; args.getSlice(2, argsTail); return new ScheduledAction(v, argsTail); }
PassOwnPtr<ScheduledAction> ScheduledAction::create(ExecState* exec, const ArgList& args, DOMWrapperWorld* isolatedWorld) { JSValue v = args.at(0); CallData callData; if (v.getCallData(callData) == CallTypeNone) { UString string = v.toString(exec); if (exec->hadException()) return 0; return new ScheduledAction(string, isolatedWorld); } ArgList argsTail; args.getSlice(2, argsTail); return new ScheduledAction(v, argsTail, isolatedWorld); }
bool _NPN_Invoke(NPP npp, NPObject* o, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result) { if (o->_class == NPScriptObjectClass) { JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o); IdentifierRep* i = static_cast<IdentifierRep*>(methodName); if (!i->isString()) return false; // Special case the "eval" method. if (methodName == _NPN_GetStringIdentifier("eval")) { if (argCount != 1) return false; if (args[0].type != NPVariantType_String) return false; return _NPN_Evaluate(npp, o, const_cast<NPString*>(&args[0].value.stringValue), result); } // Look up the function object. RootObject* rootObject = obj->rootObject; if (!rootObject || !rootObject->isValid()) return false; ExecState* exec = rootObject->globalObject()->globalExec(); JSLock lock(SilenceAssertionsOnly); JSValue function = obj->imp->get(exec, identifierFromNPIdentifier(i->string())); CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return false; // Call the function object. MarkedArgumentBuffer argList; getListFromVariantArgs(exec, args, argCount, rootObject, argList); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); globalObject->globalData()->timeoutChecker.start(); JSValue resultV = JSC::call(exec, function, callType, callData, obj->imp, argList); globalObject->globalData()->timeoutChecker.stop(); // Convert and return the result of the function call. convertValueToNPVariant(exec, resultV, result); exec->clearException(); return true; } if (o->_class->invoke) return o->_class->invoke(o, methodName, args, argCount, result); VOID_TO_NPVARIANT(*result); return true; }
String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix) { ASSERT(m_customResolver); if (!m_frame) return String(); if (!m_frame->script()->isEnabled()) return String(); JSLock lock(false); JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); JSValue* function = m_customResolver->get(exec, Identifier(exec, "lookupNamespaceURI")); CallData callData; CallType callType = function->getCallData(callData); if (callType == CallTypeNone) { callType = m_customResolver->getCallData(callData); if (callType == CallTypeNone) { // FIXME: Pass actual line number and source URL. m_frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method.", 0, String()); return String(); } function = m_customResolver; } RefPtr<JSCustomXPathNSResolver> selfProtector(this); ArgList args; args.append(jsString(exec, prefix)); globalObject->startTimeoutCheck(); JSValue* retval = call(exec, function, callType, callData, m_customResolver, args); globalObject->stopTimeoutCheck(); String result; if (exec->hadException()) reportCurrentException(exec); else { if (!retval->isUndefinedOrNull()) result = retval->toString(exec); } Document::updateDocumentsRendering(); return result; }
void JSCustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bool& raisedException) { ASSERT(m_data); ASSERT(m_data->callback()); ASSERT(m_data->frame()); if (!m_data->frame()->script()->isEnabled()) return; JSGlobalObject* globalObject = m_data->frame()->script()->globalObject(); ExecState* exec = globalObject->globalExec(); JSC::JSLock lock(false); JSValue* handleEventFunction = m_data->callback()->get(exec, Identifier(exec, "handleEvent")); CallData handleEventCallData; CallType handleEventCallType = handleEventFunction->getCallData(handleEventCallData); CallData callbackCallData; CallType callbackCallType = CallTypeNone; if (handleEventCallType == CallTypeNone) { callbackCallType = m_data->callback()->getCallData(callbackCallData); if (callbackCallType == CallTypeNone) { // FIXME: Should an exception be thrown here? return; } } RefPtr<JSCustomSQLTransactionCallback> protect(this); ArgList args; args.append(toJS(exec, transaction)); globalObject->startTimeoutCheck(); if (handleEventCallType != CallTypeNone) call(exec, handleEventFunction, handleEventCallType, handleEventCallData, m_data->callback(), args); else call(exec, m_data->callback(), callbackCallType, callbackCallData, m_data->callback(), args); globalObject->stopTimeoutCheck(); if (exec->hadException()) { m_data->frame()->domWindow()->console()->reportCurrentException(exec); raisedException = true; } Document::updateDocumentsRendering(); }
void JSCustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) { ASSERT(m_callback); ASSERT(m_frame); if (!m_frame->script()->isEnabled()) return; // FIXME: This is likely the wrong globalObject (for prototype chains at least) JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); JSC::JSLock lock(SilenceAssertionsOnly); JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) { callType = m_callback->getCallData(callData); if (callType == CallTypeNone) { // FIXME: Should an exception be thrown here? return; } function = m_callback; } RefPtr<JSCustomSQLStatementCallback> protect(this); MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), resultSet)); globalObject->globalData()->timeoutChecker.start(); call(exec, function, callType, callData, m_callback, args); globalObject->globalData()->timeoutChecker.stop(); if (exec->hadException()) { reportCurrentException(exec); raisedException = true; } Document::updateStyleForAllDocuments(); }
void JSCustomVoidCallback::handleEvent() { ASSERT(m_callback); ASSERT(m_frame); if (!m_frame->script()->isEnabled()) return; JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); KJS::JSLock lock; JSValue* function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; CallType callType = function->getCallData(callData); if (callType == CallTypeNone) { callType = m_callback->getCallData(callData); if (callType == CallTypeNone) { // FIXME: Should an exception be thrown here? return; } function = m_callback; } RefPtr<JSCustomVoidCallback> protect(this); ArgList args; globalObject->startTimeoutCheck(); call(exec, function, callType, callData, m_callback, args); globalObject->stopTimeoutCheck(); if (exec->hadException()) { JSObject* exception = exec->exception()->toObject(exec); String message = exception->get(exec, exec->propertyNames().message)->toString(exec); int lineNumber = exception->get(exec, Identifier(exec, "line"))->toInt32(exec); String sourceURL = exception->get(exec, Identifier(exec, "sourceURL"))->toString(exec); m_frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, message, lineNumber, sourceURL); exec->clearException(); } Document::updateDocumentsRendering(); }
bool JSCustomSQLTransactionErrorCallback::handleEvent(SQLError* error) { ASSERT(m_callback); ASSERT(m_frame); if (!m_frame->script()->isEnabled()) return true; JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); JSC::JSLock lock(false); JSValue* function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; CallType callType = function->getCallData(callData); if (callType == CallTypeNone) { callType = m_callback->getCallData(callData); if (callType == CallTypeNone) { // FIXME: Should an exception be thrown here? return true; } function = m_callback; } RefPtr<JSCustomSQLTransactionErrorCallback> protect(this); ArgList args; args.append(toJS(exec, error)); JSValue *result; globalObject->startTimeoutCheck(); result = call(exec, function, callType, callData, m_callback, args); globalObject->stopTimeoutCheck(); if (exec->hadException()) m_frame->domWindow()->console()->reportCurrentException(exec); Document::updateDocumentsRendering(); return result->toBoolean(exec); }
String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix) { ASSERT(m_customResolver); JSLock lock(SilenceAssertionsOnly); ExecState* exec = m_globalObject->globalExec(); JSValue function = m_customResolver->get(exec, Identifier(exec, "lookupNamespaceURI")); CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) { callType = m_customResolver->getCallData(callData); if (callType == CallTypeNone) { // FIXME: Pass actual line number and source URL. m_globalObject->impl()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method.", 0, String()); return String(); } function = m_customResolver; } RefPtr<JSCustomXPathNSResolver> selfProtector(this); MarkedArgumentBuffer args; args.append(jsString(exec, prefix)); m_globalObject->globalData()->timeoutChecker.start(); JSValue retval = call(exec, function, callType, callData, m_customResolver, args); m_globalObject->globalData()->timeoutChecker.stop(); String result; if (exec->hadException()) reportCurrentException(exec); else { if (!retval.isUndefinedOrNull()) result = retval.toString(exec); } Document::updateStyleForAllDocuments(); return result; }
static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName) { JSValue function = object->get(exec, propertyName); CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return exec->exception(); // Prevent "toString" and "valueOf" from observing execution if an exception // is pending. if (exec->hadException()) return exec->exception(); JSValue result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList()); ASSERT(!result.isGetterSetter()); if (exec->hadException()) return exec->exception(); if (result.isObject()) return JSValue(); return result; }
bool _NPN_InvokeDefault(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, NPVariant* result) { if (o->_class == NPScriptObjectClass) { JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o); VOID_TO_NPVARIANT(*result); // Lookup the function object. RootObject* rootObject = obj->rootObject; if (!rootObject || !rootObject->isValid()) return false; ExecState* exec = rootObject->globalObject()->globalExec(); JSLock lock(SilenceAssertionsOnly); // Call the function object. JSValue function = obj->imp; CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return false; MarkedArgumentBuffer argList; getListFromVariantArgs(exec, args, argCount, rootObject, argList); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); globalObject->globalData()->timeoutChecker.start(); JSValue resultV = JSC::call(exec, function, callType, callData, function, argList); globalObject->globalData()->timeoutChecker.stop(); // Convert and return the result of the function call. convertValueToNPVariant(exec, resultV, result); exec->clearException(); return true; } if (o->_class->invokeDefault) return o->_class->invokeDefault(o, args, argCount, result); VOID_TO_NPVARIANT(*result); return true; }
JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { JSObject* object = thisValue.toThisObject(exec); if (exec->hadException()) return jsNull(); JSValue toISOValue = object->get(exec, exec->globalData().propertyNames->toISOString); if (exec->hadException()) return jsNull(); CallData callData; CallType callType = toISOValue.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError, "toISOString is not a function"); JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList()); if (exec->hadException()) return jsNull(); if (result.isObject()) return throwError(exec, TypeError, "toISOString did not return a primitive value"); return result; }
void JSCustomVoidCallback::handleEvent() { ASSERT(m_callback); ASSERT(m_frame); if (!m_frame->script()->isEnabled()) return; JSGlobalObject* globalObject = m_frame->script()->globalObject(); ExecState* exec = globalObject->globalExec(); JSC::JSLock lock(SilenceAssertionsOnly); JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent")); CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) { callType = m_callback->getCallData(callData); if (callType == CallTypeNone) { // FIXME: Should an exception be thrown here? return; } function = m_callback; } RefPtr<JSCustomVoidCallback> protect(this); MarkedArgumentBuffer args; globalObject->globalData()->timeoutChecker.start(); call(exec, function, callType, callData, m_callback, args); globalObject->globalData()->timeoutChecker.stop(); if (exec->hadException()) reportCurrentException(exec); Document::updateStyleForAllDocuments(); }
JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { JSString* sourceVal = thisValue.toThisJSString(exec); const UString& source = sourceVal->value(); JSValue pattern = args.at(0); JSValue replacement = args.at(1); UString replacementString; CallData callData; CallType callType = replacement.getCallData(callData); if (callType == CallTypeNone) replacementString = replacement.toString(exec); if (pattern.isObject(&RegExpObject::info)) { RegExp* reg = asRegExpObject(pattern)->regExp(); bool global = reg->global(); RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int lastIndex = 0; int startPosition = 0; Vector<UString::Range, 16> sourceRanges; Vector<UString, 16> replacements; // This is either a loop (if global is set) or a one-way (if not). if (global && callType == CallTypeJS) { // reg->numSubpatterns() + 1 for pattern args, + 2 for match start and sourceValue int argCount = reg->numSubpatterns() + 1 + 2; JSFunction* func = asFunction(replacement); CachedCall cachedCall(exec, func, argCount, exec->exceptionSlot()); if (exec->hadException()) return jsNull(); while (true) { int matchIndex; int matchLen; int* ovector; regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); if (matchIndex < 0) break; sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); int completeMatchStart = ovector[0]; unsigned i = 0; for (; i < reg->numSubpatterns() + 1; ++i) { int matchStart = ovector[i * 2]; int matchLen = ovector[i * 2 + 1] - matchStart; if (matchStart < 0) cachedCall.setArgument(i, jsUndefined()); else cachedCall.setArgument(i, jsSubstring(exec, source, matchStart, matchLen)); } cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart)); cachedCall.setArgument(i++, sourceVal); cachedCall.setThis(exec->globalThisValue()); replacements.append(cachedCall.call().toString(cachedCall.newCallFrame())); if (exec->hadException()) break; lastIndex = matchIndex + matchLen; startPosition = lastIndex; // special case of empty match if (matchLen == 0) { startPosition++; if (startPosition > source.size()) break; } } } else { do { int matchIndex; int matchLen; int* ovector; regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); if (matchIndex < 0) break; sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); if (callType != CallTypeNone) { int completeMatchStart = ovector[0]; MarkedArgumentBuffer args; for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) { int matchStart = ovector[i * 2]; int matchLen = ovector[i * 2 + 1] - matchStart; if (matchStart < 0) args.append(jsUndefined()); else args.append(jsSubstring(exec, source, matchStart, matchLen)); } args.append(jsNumber(exec, completeMatchStart)); args.append(sourceVal); replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec)); if (exec->hadException()) break; } else replacements.append(substituteBackreferences(replacementString, source, ovector, reg)); lastIndex = matchIndex + matchLen; startPosition = lastIndex; // special case of empty match if (matchLen == 0) { startPosition++; if (startPosition > source.size()) break; } } while (global); } if (!lastIndex && replacements.isEmpty()) return sourceVal; if (lastIndex < source.size()) sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex)); return jsString(exec, source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size())); } // Not a regular expression, so treat the pattern as a string. UString patternString = pattern.toString(exec); int matchPos = source.find(patternString); if (matchPos == -1) return sourceVal; int matchLen = patternString.size(); if (callType != CallTypeNone) { MarkedArgumentBuffer args; args.append(jsSubstring(exec, source, matchPos, matchLen)); args.append(jsNumber(exec, matchPos)); args.append(sourceVal); replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec); } int ovector[2] = { matchPos, matchPos + matchLen }; return jsString(exec, source.replaceRange(matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0))); }
JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { JSString* sourceVal = thisValue->toThisJSString(exec); const UString& source = sourceVal->value(); JSValue* pattern = args.at(exec, 0); JSValue* replacement = args.at(exec, 1); UString replacementString; CallData callData; CallType callType = replacement->getCallData(callData); if (callType == CallTypeNone) replacementString = replacement->toString(exec); if (pattern->isObject(&RegExpObject::info)) { RegExp* reg = static_cast<RegExpObject*>(pattern)->regExp(); bool global = reg->global(); RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor(); int lastIndex = 0; int startPosition = 0; Vector<UString::Range, 16> sourceRanges; Vector<UString, 16> replacements; // This is either a loop (if global is set) or a one-way (if not). do { int matchIndex; int matchLen; int* ovector; regExpObj->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); if (matchIndex < 0) break; sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); if (callType != CallTypeNone) { int completeMatchStart = ovector[0]; ArgList args; for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) { int matchStart = ovector[i * 2]; int matchLen = ovector[i * 2 + 1] - matchStart; if (matchStart < 0) args.append(jsUndefined()); else args.append(jsSubstring(exec, source, matchStart, matchLen)); } args.append(jsNumber(exec, completeMatchStart)); args.append(sourceVal); replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec)); } else replacements.append(substituteBackreferences(replacementString, source, ovector, reg)); lastIndex = matchIndex + matchLen; startPosition = lastIndex; // special case of empty match if (matchLen == 0) { startPosition++; if (startPosition > source.size()) break; } } while (global); if (lastIndex < source.size()) sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex)); UString result = source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()); if (result == source) return sourceVal; return jsString(exec, result); } // First arg is a string UString patternString = pattern->toString(exec); int matchPos = source.find(patternString); int matchLen = patternString.size(); // Do the replacement if (matchPos == -1) return sourceVal; if (callType != CallTypeNone) { ArgList args; args.append(jsSubstring(exec, source, matchPos, matchLen)); args.append(jsNumber(exec, matchPos)); args.append(sourceVal); replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec); } return jsString(exec, source.substr(0, matchPos) + replacementString + source.substr(matchPos + matchLen)); }
void JSAbstractEventListener::handleEvent(Event* event, bool isWindowEvent) { JSObject* listener = listenerObj(); if (!listener) return; JSDOMWindow* window = this->window(); // Null check as clearWindow() can clear this and we still get called back by // xmlhttprequest objects. See http://bugs.webkit.org/show_bug.cgi?id=13275 if (!window) return; Frame* frame = window->impl()->frame(); if (!frame) return; ScriptController* script = frame->script(); if (!script->isEnabled() || script->isPaused()) return; JSLock lock(false); ExecState* exec = window->globalExec(); JSValue* handleEventFunction = listener->get(exec, Identifier(exec, "handleEvent")); CallData callData; CallType callType = handleEventFunction->getCallData(callData); if (callType == CallTypeNone) { handleEventFunction = 0; callType = listener->getCallData(callData); } if (callType != CallTypeNone) { ref(); ArgList args; args.append(toJS(exec, event)); Event* savedEvent = window->currentEvent(); window->setCurrentEvent(event); JSValue* retval; if (handleEventFunction) { window->startTimeoutCheck(); retval = call(exec, handleEventFunction, callType, callData, listener, args); } else { JSValue* thisValue; if (isWindowEvent) thisValue = window->shell(); else thisValue = toJS(exec, event->currentTarget()); window->startTimeoutCheck(); retval = call(exec, listener, callType, callData, thisValue, args); } window->stopTimeoutCheck(); window->setCurrentEvent(savedEvent); if (exec->hadException()) frame->domWindow()->console()->reportCurrentException(exec); else { if (!retval->isUndefinedOrNull() && event->storesResultAsString()) event->storeResult(retval->toString(exec)); if (m_isHTML) { bool retvalbool; if (retval->getBoolean(retvalbool) && !retvalbool) event->preventDefault(); } } Document::updateDocumentsRendering(); deref(); } }
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(); } }
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) { ASSERT(scriptExecutionContext); if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionTerminated()) return; JSLock lock(SilenceAssertionsOnly); JSObject* jsFunction = this->jsFunction(scriptExecutionContext); if (!jsFunction) return; JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld.get()); if (!globalObject) 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->canExecuteScripts(AboutToExecuteScript) || 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); JSGlobalData* globalData = globalObject->globalData(); DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject); globalData->timeoutChecker.start(); JSValue retval = handleEventFunction ? JSC::call(exec, handleEventFunction, callType, callData, jsFunction, args) : JSC::call(exec, jsFunction, callType, callData, toJS(exec, globalObject, event->currentTarget()), args); globalData->timeoutChecker.stop(); globalObject->setCurrentEvent(savedEvent); if (exec->hadException()) #if PLATFORM(APOLLO) reportApolloException(globalObject); #else reportCurrentException(exec); #endif else { if (!retval.isUndefinedOrNull() && event->storesResultAsString())
// ES5 8.10.5 ToPropertyDescriptor static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc) { if (!in.isObject()) { throwError(exec, TypeError, "Property description must be an object."); return false; } JSObject* description = asObject(in); PropertySlot enumerableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) { desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec)); if (exec->hadException()) return false; } PropertySlot configurableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) { desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec)); if (exec->hadException()) return false; } JSValue value; PropertySlot valueSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) { desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value)); if (exec->hadException()) return false; } PropertySlot writableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) { desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec)); if (exec->hadException()) return false; } PropertySlot getSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) { JSValue get = getSlot.getValue(exec, exec->propertyNames().get); if (exec->hadException()) return false; if (!get.isUndefined()) { CallData callData; if (get.getCallData(callData) == CallTypeNone) { throwError(exec, TypeError, "Getter must be a function."); return false; } } else get = JSValue(); desc.setGetter(get); } PropertySlot setSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) { JSValue set = setSlot.getValue(exec, exec->propertyNames().set); if (exec->hadException()) return false; if (!set.isUndefined()) { CallData callData; if (set.getCallData(callData) == CallTypeNone) { throwError(exec, TypeError, "Setter must be a function."); return false; } } else set = JSValue(); desc.setSetter(set); } if (!desc.isAccessorDescriptor()) return true; if (desc.value()) { throwError(exec, TypeError, "Invalid property. 'value' present on property with getter or setter."); return false; } if (desc.writablePresent()) { throwError(exec, TypeError, "Invalid property. 'writable' present on property with getter or setter."); return false; } return true; }