bool JSTestCallbackFunction::callbackRequiresThisToPass(int longParam, TestNode* testNodeParam) { if (!canInvokeCallback()) return true; Ref<JSTestCallbackFunction> protect(*this); JSLockHolder lock(m_data->globalObject()->vm()); ExecState* state = m_data->globalObject()->globalExec(); MarkedArgumentBuffer args; args.append(jsNumber(longParam)); args.append(toJS(state, m_data->globalObject(), WTF::getPtr(testNodeParam))); NakedPtr<Exception> returnedException; UNUSED_PARAM(state); m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException); if (returnedException) reportException(state, returnedException); return !returnedException; }
bool JSTestCallbackFunction::callbackWithSerializedScriptValueParam(PassRefPtr<SerializedScriptValue> srzParam, const String& strArg) { if (!canInvokeCallback()) return true; Ref<JSTestCallbackFunction> protectedThis(*this); JSLockHolder lock(m_data->globalObject()->vm()); ExecState* state = m_data->globalObject()->globalExec(); MarkedArgumentBuffer args; args.append(srzParam ? srzParam->deserialize(state, castedThis->globalObject(), 0) : jsNull()); args.append(jsStringWithCache(state, strArg)); NakedPtr<Exception> returnedException; UNUSED_PARAM(state); m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException); if (returnedException) reportException(state, returnedException); return !returnedException; }
/** * The Rexx stub for the Queue PUT method. replaces the Array * version because it has slightly different semantics for index * validation. The only valid indexes are those within range * and the size is not adjusted for a put out of bounds. * * @param arguments The array of all arguments sent to the * method (variable arguments allowed * here...the first argument is the item being * added, all other arguments are the index). * @param argCount The number of arguments in the method call. * * @return Always return nothing. */ RexxObject *QueueClass::putRexx(RexxObject *value, RexxObject *index) { requiredArgument(value, ARG_ONE); // make sure we have an index specified before trying to decode this. requiredArgument(index, ARG_TWO); // Validate the index argument, but don't allow expansion. size_t position; if (!validateIndex(&index, 1, ARG_TWO, IndexAccess, position)) { reportException(Error_Incorrect_method_index, index); } // we can only update assigned items, so make sure this is within bounds. checkInsertIndex(position); // set the new value and return nothing put(value, position); return OREF_NULL; }
ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld* world) { const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); String sourceURL = ustringToString(jsSourceCode.provider()->url()); // evaluate code. Returns the JS return value or 0 // if there was none, an error occurred or the type couldn't be converted. // inlineCode is true for <a href="javascript:doSomething()"> // and false for <script>doSomething()</script>. Check if it has the // expected value in all cases. // See smart window.open policy for where this is used. JSDOMWindowShell* shell = windowShell(world); ExecState* exec = shell->window()->globalExec(); const String* savedSourceURL = m_sourceURL; m_sourceURL = &sourceURL; JSLock lock(SilenceAssertionsOnly); RefPtr<Frame> protect = m_frame; InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, sourceCode.startLine()); JSValue evaluationException; exec->globalData().timeoutChecker.start(); JSValue returnValue = JSMainThreadExecState::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, shell, &evaluationException); exec->globalData().timeoutChecker.stop(); InspectorInstrumentation::didEvaluateScript(cookie); if (evaluationException) { reportException(exec, evaluationException); m_sourceURL = savedSourceURL; return ScriptValue(); } m_sourceURL = savedSourceURL; return ScriptValue(exec->globalData(), returnValue); }
Deprecated::ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld& world) { const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); String sourceURL = jsSourceCode.provider()->url(); // evaluate code. Returns the JS return value or 0 // if there was none, an error occurred or the type couldn't be converted. // inlineCode is true for <a href="javascript:doSomething()"> // and false for <script>doSomething()</script>. Check if it has the // expected value in all cases. // See smart window.open policy for where this is used. JSDOMWindowShell* shell = windowShell(world); ExecState* exec = shell->window()->globalExec(); const String* savedSourceURL = m_sourceURL; m_sourceURL = &sourceURL; JSLockHolder lock(exec); Ref<Frame> protect(m_frame); InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(&m_frame, sourceURL, sourceCode.startLine()); JSValue evaluationException; JSValue returnValue = JSMainThreadExecState::evaluate(exec, jsSourceCode, shell, &evaluationException); InspectorInstrumentation::didEvaluateScript(cookie, &m_frame); if (evaluationException) { reportException(exec, evaluationException, sourceCode.cachedScript()); m_sourceURL = savedSourceURL; return Deprecated::ScriptValue(); } m_sourceURL = savedSourceURL; return Deprecated::ScriptValue(exec->vm(), returnValue); }
ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) { // evaluate code. Returns the JS return value or 0 // if there was none, an error occured or the type couldn't be converted. const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); initScriptIfNeeded(); // inlineCode is true for <a href="javascript:doSomething()"> // and false for <script>doSomething()</script>. Check if it has the // expected value in all cases. // See smart window.open policy for where this is used. ExecState* exec = m_windowShell->window()->globalExec(); const String* savedSourceURL = m_sourceURL; String sourceURL = jsSourceCode.provider()->url(); m_sourceURL = &sourceURL; JSLock lock(false); // Evaluating the JavaScript could cause the frame to be deallocated // so we start the keep alive timer here. m_frame->keepAlive(); m_windowShell->window()->startTimeoutCheck(); Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, m_windowShell); m_windowShell->window()->stopTimeoutCheck(); if (comp.complType() == Normal || comp.complType() == ReturnValue) { m_sourceURL = savedSourceURL; return comp.value(); } if (comp.complType() == Throw) reportException(exec, comp.value()); m_sourceURL = savedSourceURL; return noValue(); }
/** * Execute an attribute-get operation. * * @param activity The current activity. * @param method The method we're invoking. * @param receiver The receiver object. * @param messageName * The name of the message used to invoke the method. * @param argPtr The pointer to the arguments. * @param count The argument count. * @param result The returned result. */ void AttributeGetterCode::run(Activity *activity, MethodClass *method, RexxObject *receiver, RexxString *messageName, RexxObject **argPtr, size_t count, ProtectedObject &result) { // validate the number of arguments if (count > 0) { reportException(Error_Incorrect_method_maxarg, (wholenumber_t)0); } // this is simplier if the method is not guarded if (!method->isGuarded()) { result = attribute->getValue(receiver->getObjectVariables(method->getScope())); } else { // get the variable pool and get the guard lock VariableDictionary *objectVariables = receiver->getObjectVariables(method->getScope()); objectVariables->reserve(activity); result = attribute->getValue(objectVariables); // and ensure we release this afterwards objectVariables->release(activity); } }
size_t RexxEnvelope::copyBuffer( RexxObject *obj) /* object to copy */ /******************************************************************************/ /* Function: Copy an object into our flatten buffer */ /******************************************************************************/ { // copy the object into the buffer, which might cause the buffer to // resize itself. size_t objOffset = this->buffer->copyData((void *)obj, obj->getObjectSize()); // get a reference to the copied object RexxObject *newObj = (RexxObject *) (this->buffer->getBuffer()->getData() + objOffset); // if this is a non-primative behaviour, we need to flatten it as well. The // offset is tagged as being a non-primitive behaviour that needs later inflating. if (newObj->behaviour->isNonPrimitive()) { void *behavPtr = &newObj->behaviour; this->flattenReference(&newObj, objOffset, (RexxObject **)behavPtr); } else { // transient classes should never be flattened. This is a problem if we encounter one if (newObj->behaviour->isTransientClass()) { reportException(Error_Interpretation); } // just replace the behaviour with its normalized type number. This will be used // to restore it later. newObj->behaviour = newObj->behaviour->getSavedPrimitiveBehaviour(); } // if we flattened an object from oldspace, we just copied everything. Make sure // this is no longer marked as oldspace newObj->setNewSpace(); // the offset is what we need return objOffset; }
bool ScriptDebugServer::evaluateBreakpointAction(const ScriptBreakpointAction& breakpointAction) const { DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame(); switch (breakpointAction.type) { case ScriptBreakpointActionTypeLog: { DOMWindow& window = asJSDOMWindow(debuggerCallFrame->dynamicGlobalObject())->impl(); if (PageConsole* console = window.pageConsole()) console->addMessage(JSMessageSource, LogMessageLevel, breakpointAction.data); break; } case ScriptBreakpointActionTypeEvaluate: { JSValue exception; debuggerCallFrame->evaluate(breakpointAction.data, exception); if (exception) reportException(debuggerCallFrame->exec(), exception); break; } case ScriptBreakpointActionTypeSound: systemBeep(); break; } return true; }
/** * Run a routine for a thread context API call. */ void CallProgramDispatcher::run() { RexxString *targetName = new_string(program); //we are resolving from a program name RexxString *name = activity->resolveProgramName(targetName, OREF_NULL, OREF_NULL); if (name == OREF_NULL) { reportException(Error_Program_unreadable_notfound, targetName); } ProtectedObject p(name); // create a routine from this file Protected<RoutineClass> routine = LanguageParser::createProgramFromFile(name); if (arguments != OREF_NULL) { // use the provided name for the call name routine->runProgram(activity, arguments->messageArgs(), arguments->messageArgCount(), result); } else { // we use a null string for the name when things are called directly routine->runProgram(activity, NULL, 0, result); } }
void V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context, Event* event, v8::Handle<v8::Value> jsEvent) { v8::Local<v8::Context> v8Context = toV8Context(context, worldContext()); if (v8Context.IsEmpty()) return; // We push the event being processed into the global object, so that it can be exposed by DOMWindow's bindings. v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event"); v8::Local<v8::Value> returnValue; // In beforeunload/unload handlers, we want to avoid sleeps which do tight loops of calling Date.getTime(). if (event->type() == "beforeunload" || event->type() == "unload") DateExtension::get()->setAllowSleep(false); { // 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 = v8Context->Global()->GetHiddenValue(eventSymbol); tryCatch.Reset(); // Make the event available in the global object, so DOMWindow can expose it. v8Context->Global()->SetHiddenValue(eventSymbol, jsEvent); tryCatch.Reset(); // Call the event handler. returnValue = callListenerFunction(context, jsEvent, event); if (!tryCatch.CanContinue()) return; // If an error occurs while handling the event, it should be reported. if (tryCatch.HasCaught()) { reportException(0, tryCatch); tryCatch.Reset(); } // Restore the old event. This must be done for all exit paths through this method. if (savedEvent.IsEmpty()) v8Context->Global()->SetHiddenValue(eventSymbol, v8::Undefined()); else v8Context->Global()->SetHiddenValue(eventSymbol, savedEvent); tryCatch.Reset(); } if (event->type() == "beforeunload" || event->type() == "unload") DateExtension::get()->setAllowSleep(true); ASSERT(!V8Proxy::handleOutOfMemory() || returnValue.IsEmpty()); if (returnValue.IsEmpty()) return; if (!returnValue->IsNull() && !returnValue->IsUndefined() && event->storesResultAsString()) event->storeResult(toWebCoreString(returnValue)); // Prevent default action if the return value is false; // FIXME: Add example, and reference to bug entry. if (m_isAttribute && returnValue->IsBoolean() && !returnValue->BooleanValue()) event->preventDefault(); }
/** * Default virtual method for handling a run() methods on * an activity dispatcher. */ void RexxStartDispatcher::run() { ProtectedSet savedObjects; // set default return values rc = 0; retcode = 0; RexxString *name = OREF_NULLSTRING; // name of the invoked program RexxString *fullname = name; // default the fulllength name to the simple name if (programName != NULL) /* have an actual name? */ { /* get string version of the name */ name = new_string(programName); } savedObjects.add(name); /* protect from garbage collect */ // get an array version of the arguments and protect RexxArray *new_arglist = new_array(argcount + 1); // + 1 to store count of named arguments = 0 savedObjects.add(new_arglist); // for compatibility reasons, if this is a command invocation and there is a leading blank // on the only argument, then remove that leading blank from the argument if (calltype == RXCOMMAND && argcount == 1 && arglist[0].strlength > 1 && arglist[0].strptr != NULL && arglist[0].strptr[0] == ' ') { new_arglist->put(new_string(arglist[0].strptr + 1, arglist[0].strlength - 1), 1); } else { /* loop through the argument list */ for (size_t i = 0; i < argcount; i++) { /* have a real argument? */ if (arglist[i].strptr != NULL) { /* add to the argument array */ new_arglist->put(new_string(arglist[i]), i + 1); } } } // Counter of named arguments. To support correctly omitted positional arguments, don't use append! // Omitted positional arguments not applicable here, but better to have the same approach everywhere. // Here, no named arguments : Zero. new_arglist->put(IntegerZero, argcount + 1); RexxString *source_calltype; switch (calltype) /* turn calltype into a string */ { case RXCOMMAND: /* command invocation */ source_calltype = OREF_COMMAND; /* this is the 'COMMAND' string */ break; case RXFUNCTION: /* function invocation */ /* 'FUNCTION' string */ source_calltype = OREF_FUNCTIONNAME; break; case RXSUBROUTINE: /* subroutine invocation */ /* 'SUBROUTINE' string */ source_calltype = OREF_SUBROUTINE; break; default: source_calltype = OREF_COMMAND; /* this is the 'COMMAND' string */ break; } RoutineClass *program = OREF_NULL; if (instore == NULL) /* no instore request? */ { /* go resolve the name */ fullname = activity->resolveProgramName(name, OREF_NULL, OREF_NULL); if (fullname == OREF_NULL) /* not found? */ { /* got an error here */ reportException(Error_Program_unreadable_notfound, name); } savedObjects.add(fullname); /* try to restore saved image */ program = RoutineClass::fromFile(fullname); } else /* have an instore program */ { /* go handle instore parms */ program = RoutineClass::processInstore(instore, name); if (program == OREF_NULL) /* couldn't get it? */ { /* got an error here */ reportException(Error_Program_unreadable_name, name); } } RexxString *initial_address = activity->getInstance()->getDefaultEnvironment(); /* actually need to run this? */ if (program != OREF_NULL) { ProtectedObject program_result; // call the program program->runProgram(activity, source_calltype, initial_address, new_arglist->data(), argcount, program_result); if (result != NULL) /* if return provided for */ { /* actually have a result to return? */ if ((RexxObject *)program_result != OREF_NULL) { /* force to a string value */ program_result = ((RexxObject *)program_result)->stringValue(); // copy this into the result RXSTRING ((RexxString *)program_result)->copyToRxstring(*result); } else /* make this an invalid string */ { MAKERXSTRING(*result, NULL, 0); } } /* If there is a return val... */ if ((RexxObject *)program_result != OREF_NULL) { wholenumber_t return_code; /* if a whole number... */ if (((RexxObject *)program_result)->numberValue(return_code) && return_code <= SHRT_MAX && return_code >= SHRT_MIN) { /* ...copy to return code. */ retcode = (short)return_code; } } } }
/** * Default virtual method for handling a run() methods on * an activity dispatcher. */ void RexxStartDispatcher::run() { ProtectedSet savedObjects; // set default return values rc = 0; retcode = 0; RexxString *name = GlobalNames::NULLSTRING; // name of the invoked program RexxString *fullname = name; // default the fulllength name to the simple name // if we've been given an actual name, get the string version of it if (programName != NULL) { name = new_string(programName); savedObjects.add(name); } // get an array version of the arguments and protect ArrayClass *new_arglist = new_array(argcount); savedObjects.add(new_arglist); // for compatibility reasons, if this is a command invocation and there is a leading blank // on the only argument, then remove that leading blank from the argument if (calltype == RXCOMMAND && argcount == 1 && arglist[0].strlength > 1 && arglist[0].strptr != NULL && arglist[0].strptr[0] == ' ') { new_arglist->put(new_string(arglist[0].strptr + 1, arglist[0].strlength - 1), 1); } // we need to create an array argument list from the RXSTRINGs else { for (size_t i = 0; i < argcount; i++) { // only add real arguments if (arglist[i].strptr != NULL) { new_arglist->put(new_string(arglist[i]), i + 1); } } } RexxString *source_calltype; // now get the calltype as a character string to used in // the source string. . switch (calltype) { case RXCOMMAND: source_calltype = GlobalNames::COMMAND; break; case RXFUNCTION: source_calltype = GlobalNames::FUNCTION; break; case RXSUBROUTINE: source_calltype = GlobalNames::SUBROUTINE; break; // if not specified, call it a COMMAND. default: source_calltype = GlobalNames::COMMAND; break; } Protected<RoutineClass> program; // if not an instore request, we load this from a file. if (instore == NULL) { fullname = activity->resolveProgramName(name, OREF_NULL, OREF_NULL); if (fullname == OREF_NULL) { reportException(Error_Program_unreadable_notfound, name); } savedObjects.add(fullname); program = LanguageParser::createProgramFromFile(fullname); } // we either need to parse the instore source or restore from a // previous image. else { program = LanguageParser::processInstore(instore, name); if (program.isNull()) { reportException(Error_Program_unreadable_name, name); } } RexxString *initial_address = activity->getInstance()->getDefaultEnvironment(); // actually need to run this? if (!program.isNull()) { ProtectedObject program_result; // call the program program->runProgram(activity, source_calltype, initial_address, new_arglist->messageArgs(), argcount, program_result); // provided for a return result (that's optional) if (result != NULL) { // actually have a result to return? if (!program_result.isNull()) { // force to a string value program_result = program_result->stringValue(); // copy this into the result RXSTRING ((RexxString *)program_result)->copyToRxstring(*result); } // nothing to return else { MAKERXSTRING(*result, NULL, 0); } } // if we have a return result and it is an integer value, return that as a return code. if (!program_result.isNull()) { wholenumber_t return_code; if (program_result->numberValue(return_code) && return_code <= SHRT_MAX && return_code >= SHRT_MIN) { retcode = (short)return_code; } } } }
/** * Perform the Arithmetic power operation * * @param PowerObj The power we're raising this number to. * * @return The power result. */ NumberString *NumberString::power(RexxObject *powerObj) { requiredArgument(powerObj, ARG_ONE); wholenumber_t powerValue; if (!powerObj->numberValue(powerValue, number_digits())) { reportException(Error_Invalid_whole_number_power, powerObj); } bool negativePower = false; // if the power is negative, we'll first calculate the power // as a positive and take the reciprical at the end. if (powerValue < 0) { negativePower = true; powerValue = -powerValue; } wholenumber_t digits = number_digits(); // get a potential copy of this, truncated to have at most digits + 1 digits. NumberString *left = prepareOperatorNumber(digits + 1, digits, NOROUND); // if we are raising zero to a power, there are some special rules in play here. if (left->isZero()) { // if the power is negative, this is an overflow error if (negativePower) { reportException(Error_Overflow_power); } // mathematically, 0**0 is undefined. Rexx defines this as 1 else if (powerValue == 0) { return (NumberString *)IntegerOne; } // zero to a non-zero power is zero else { return (NumberString *)IntegerZero; } } // we figure out ahead of time if this will overflow without having to // do all of the calculation work. This tests if we can even start the // process because it will required too many bits to calculate. This is // more likely to fail with 32-bit compiles than 64-bit because we have // fewer bits to work with. if ((highBits(Numerics::abs(left->numberExponent + left->digitsCount - 1)) + highBits(Numerics::abs(powerValue)) + 1) > SIZEBITS ) { reportException(Error_Overflow_overflow, this, GlobalNames::POWER, powerObj); } // we can also calculate the exponent magnitude ahead of time and fail this early. if (Numerics::abs(left->numberExponent + left->digitsCount - 1) * powerValue > Numerics::MAX_EXPONENT) { reportException(Error_Overflow_overflow, this, GlobalNames::POWER, powerObj); } // anything raised to the 0th power is 1, this is an easy one. if (powerValue == 0) { return (NumberString *)IntegerOne; } // we create a dummy numberstring object and initialize it from the target number NumberStringBase accumNumber = *left; NumberStringBase *accumObj = &accumNumber; // Find out how many digits are in power value, needed for actual // precision value to be used in the computation. wholenumber_t extra = 0; wholenumber_t oldNorm = powerValue; // keep dividing the value by 10 until we hit zero. That will be the number of // powers of 10 we have in the number. for (; oldNorm != 0; extra++) { oldNorm /= 10; } // add these extra digits into the working digits setting digits += (extra + 1); // and this is the size of the buffers we need for our accumulators wholenumber_t accumLen = (2 * (digits + 1)) + 1; // get a single buffer object with space for two values of this size char *outPtr = new_buffer(accumLen * 2)->getData(); char *accumBuffer = outPtr + accumLen; char *accumPtr = accumBuffer; // copy the the initial number data into the buffer memcpy(accumPtr, left->numberDigits, left->digitsCount); // the power operation is defined to use bitwise reduction size_t numBits = SIZEBITS; // get the first non-zero bit shifted to the top of the number // this will both position us to start the process and // also give us the a count of how many bits we're working with. while (!((size_t)powerValue & HIBIT)) { powerValue <<= 1; numBits--; } // turn off this 1st 1-bit, already take care of by // the starting accumulator (essentially, a multiply by 1) powerValue = (wholenumber_t) ((size_t)powerValue & LOWBITS); // ok, we know how many passes we need to make on this number. while (numBits--) { // if this bit is on, then we need to multiply the // number by the accumulator. if ((size_t) powerValue & HIBIT) { // do the multiply and get the new high position back accumPtr = multiplyPower(accumPtr, accumObj, left->numberDigits, left, outPtr, accumLen, digits); // We now call AdjustNumber to make sure we stay within the required // precision and move the Accum data back to Accum. accumPtr = accumObj->adjustNumber(accumPtr, accumBuffer, accumLen, digits); } // if we will be making another pass through this loop, we need // to square the accumulator if (numBits > 0) { accumPtr = multiplyPower(accumPtr, accumObj, accumPtr, accumObj, outPtr, accumLen, digits); // and adjust the result again accumPtr = accumObj->adjustNumber(accumPtr, accumBuffer, accumLen, digits); } // and shift to the next bit position powerValue <<= 1; } // if this was actually a negative power, take the reciprical now if (negativePower) { accumPtr = dividePower(accumPtr, accumObj, accumBuffer, digits); } // reset the digits to the original and remove all leading zeros digits -= (extra +1); // reset digits setting to original; accumPtr = accumObj->stripLeadingZeros(accumPtr); // Is result bigger than digits? if (accumObj->digitsCount > digits) { // adjust to the shorter length and round if needed accumObj->numberExponent += (accumObj->digitsCount - digits); accumObj->digitsCount = digits; accumObj->mathRound(accumPtr); } // we now remove any trailing zeros in the result (same rules as // division) char *tempPtr = accumPtr + accumObj->digitsCount - 1; /* While there are trailing zeros */ while (*tempPtr == 0 && accumObj->digitsCount > 0) { tempPtr--; accumObj->digitsCount--; accumObj->numberExponent++; } // finally build a result object. NumberString *result = new (accumObj->digitsCount) NumberString (accumObj->digitsCount); result->numberSign = accumObj->numberSign; result->numberExponent = accumObj->numberExponent; result->digitsCount = accumObj->digitsCount; memcpy(result->numberDigits, accumPtr, result->digitsCount); return result; }
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) { ASSERT(scriptExecutionContext); if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden()) return; JSLockHolder lock(scriptExecutionContext->vm()); JSObject* jsFunction = this->jsFunction(scriptExecutionContext); if (!jsFunction) return; JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, *m_isolatedWorld); if (!globalObject) return; if (scriptExecutionContext->isDocument()) { JSDOMWindow* window = jsCast<JSDOMWindow*>(globalObject); if (!window->impl().isCurrentlyDisplayedInFrame()) return; // FIXME: Is this check needed for other contexts? ScriptController& script = window->impl().frame()->script(); if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused()) return; } ExecState* exec = globalObject->globalExec(); JSValue handleEventFunction = jsFunction; CallData callData; CallType callType = getCallData(handleEventFunction, callData); // If jsFunction is not actually a function, see if it implements the EventListener interface and use that if (callType == CallTypeNone) { handleEventFunction = jsFunction->get(exec, Identifier::fromString(exec, "handleEvent")); callType = getCallData(handleEventFunction, callData); } if (callType != CallTypeNone) { Ref<JSEventListener> protect(*this); MarkedArgumentBuffer args; args.append(toJS(exec, globalObject, event)); Event* savedEvent = globalObject->currentEvent(); globalObject->setCurrentEvent(event); VM& vm = globalObject->vm(); VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject); InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData); JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event->currentTarget()) : jsFunction; NakedPtr<Exception> exception; JSValue retval = scriptExecutionContext->isDocument() ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args, exception) : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args, exception); InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext); globalObject->setCurrentEvent(savedEvent); if (is<WorkerGlobalScope>(*scriptExecutionContext)) { bool terminatorCausedException = (exec->hadException() && isTerminatedExecutionException(exec->exception())); if (terminatorCausedException || (vm.watchdog && vm.watchdog->didFire())) downcast<WorkerGlobalScope>(*scriptExecutionContext).script()->forbidExecution(); } if (exception) { event->target()->uncaughtExceptionInEventHandler(); reportException(exec, exception); } else { if (!retval.isUndefinedOrNull() && is<BeforeUnloadEvent>(*event)) downcast<BeforeUnloadEvent>(*event).setReturnValue(retval.toString(exec)->value(exec)); if (m_isAttribute) { if (retval.isFalse()) event->preventDefault(); } } } }
/** * Execute a constant get operation * * @param activity The current activity. * @param method The method we're invoking. * @param receiver The receiver object. * @param messageName * The name of the message used to invoke the method. * @param argPtr The pointer to the arguments. * @param count The argument count. * @param result The returned result. */ void AbstractCode::run(Activity *activity, MethodClass *method, RexxObject *receiver, RexxString *messageName, RexxObject **argPtr, size_t count, ProtectedObject &result) { reportException(Error_Incorrect_method_abstract, messageName); }
void ScriptDebugServer::handleExceptionInBreakpointCondition(JSC::ExecState* exec, JSC::JSValue exception) const { reportException(exec, exception); }
/** * Execute a message instruction. * * @param context The current execution context. * @param stack The current evaluation stack. */ void RexxInstructionMessage::execute(RexxActivation *context, ExpressionStack *stack) { context->traceInstruction(this); // evaluate the target object RexxObject *_target = target->evaluate(context, stack); RexxClass *_super = OREF_NULL; // do we have a superclass override? if (super != OREF_NULL) { // this is only allow if the target object is the same // as the receiver object if (_target != context->getReceiver()) { reportException(Error_Execution_super); } // get the superclass target _super = (RexxClass *)super->evaluate(context, stack); // we send the message using the stack, which // expects to find the target and the arguments // on the stack, but not the super. We need to // pop this item off after evaluation. Since this // comes either from a variable or the environment, this // is already protected from GC. stack->toss(); } // evaluate the arguments first RexxInstruction::evaluateArguments(context, stack, arguments, argumentCount); ProtectedObject result; // issue the send with or without a superclass override if (super == OREF_NULL) { stack->send(name, argumentCount, result); } else { stack->send(name, _super, argumentCount, result); } // for the instruction version, we don't worry about popping // anything off of the evaluation stack...that will be cleared automatically // when we complete. // if this is the double message version, replace the result object // with the target object. if (instructionType == KEYWORD_MESSAGE_DOUBLE) { result = _target; } // if we have a result, trace it and assign it to the variable result. if (!result.isNull()) { context->traceResult(result); context->setLocalVariable(GlobalNames::RESULT, VARIABLE_RESULT, result); } // for no result, we drop the RESULT variable else { context->dropLocalVariable(GlobalNames::RESULT, VARIABLE_RESULT); } context->pauseInstruction(); }
void RexxInstructionForward::execute( RexxActivation *context, /* current activation context */ RexxExpressionStack *stack) /* evaluation stack */ /******************************************************************************/ /* Function: Execute a forward instruction */ /******************************************************************************/ { RexxObject *_target; /* evaluated target */ RexxString *_message; /* evaluated message */ RexxObject *_superClass; /* evaluated super class */ RexxObject *result; /* message result */ RexxObject *temp; /* temporary object */ size_t count = 0; /* count of array expressions */ size_t i; /* loop counter */ RexxObject **_arguments; ProtectedObject p_message; context->traceInstruction(this); /* trace if necessary */ if (!context->inMethod()) /* is this a method clause? */ { /* raise an error */ reportException(Error_Execution_forward); } _target = OREF_NULL; /* no object yet */ _message = OREF_NULL; /* no message over ride */ _superClass = OREF_NULL; /* no super class over ride */ _arguments = OREF_NULL; /* no argument over ride */ if (this->target != OREF_NULL) /* sent to a different object? */ { /* get the expression value */ _target = this->target->evaluate(context, stack); } if (this->message != OREF_NULL) /* sending a different message? */ { /* get the expression value */ temp = this->message->evaluate(context, stack); _message = REQUEST_STRING(temp); /* get the string version */ p_message = _message; _message = _message->upper(); /* and force to uppercase */ p_message = _message; } if (this->superClass != OREF_NULL) /* overriding the super class? */ { /* get the expression value */ _superClass = this->superClass->evaluate(context, stack); } if (this->arguments != OREF_NULL) /* overriding the arguments? */ { /* get the expression value */ temp = this->arguments->evaluate(context, stack); /* get an array version */ RexxArray *argArray = REQUEST_ARRAY(temp); stack->push(argArray); /* protect this on the stack */ /* not an array item or a multiple */ /* dimension one? */ if (argArray == TheNilObject || argArray->getDimension() != 1) { /* this is an error */ reportException(Error_Execution_forward_arguments); } count = argArray->size(); /* get the size */ /* omitted trailing arguments? */ if (count != 0 && argArray->get(count) == OREF_NULL) { count--; /* decrement the count */ while (count > 0) /* loop down to first full one */ { /* find a real argument */ if (argArray->get(count) != OREF_NULL) { break; /* break out of here */ } count--; /* step back the count */ } } _arguments = argArray->data(); /* point directly to the argument data */ } if (this->array != OREF_NULL) /* have an array of extra info? */ { count = this->array->size(); /* get the expression count */ for (i = 1; i <= count; i++) /* loop through the expression list */ { RexxObject *argElement = this->array->get(i); /* real argument? */ if (argElement != OREF_NULL) { /* evaluate the expression */ argElement->evaluate(context, stack); } else { /* just push a null reference for the missing ones */ stack->push(OREF_NULL); } } /* now point at the stacked values */ _arguments = stack->arguments(count); } /* go forward this */ result = context->forward(_target, _message, _superClass, _arguments, count, instructionFlags&forward_continue); if (instructionFlags&forward_continue) /* not exiting? */ { if (result != OREF_NULL) /* result returned? */ { context->traceResult(result); /* trace if necessary */ /* set the RESULT variable to the */ /* message return value */ context->setLocalVariable(OREF_RESULT, VARIABLE_RESULT, result); } else /* drop the variable RESULT */ { context->dropLocalVariable(OREF_RESULT, VARIABLE_RESULT); } context->pauseInstruction(); /* do debug pause if necessary */ } }
void Console::reportCurrentException(ExecState* exec) { JSValue* exception = exec->exception(); exec->clearException(); reportException(exec, exception); }
/** * Divide two numbers * * @param other The left-hand-side of the division operation. * @param DivOP The type of division operation (divide, integer divide, or remainder) * * @return The division result. */ NumberString *NumberString::Division(NumberString *other, ArithmeticOperator divOP) { // buffers for intermediate results (just the numeric data) NumberStringBase accumBuffer; NumberStringBase saveLeftBuffer; NumberStringBase saveRightBuffer; // static sized buffers for typical calculation sizes. char leftBufFast[FAST_BUFFER]; char rightBufFast[FAST_BUFFER]; char outBufFast[FAST_BUFFER]; // NOTE: this is very similiar to the PowerDivide // method, these we kept as seperate routines since there // are enough subtile differences between the objectPointer operations // that combining them would make an already complex // algorithm even more so. When fixing/updating/adding to // this code also check PowerDivide for similiar updates // handle the zero cases, which are pretty quick. // if the other is zero, this is an error if (other->isZero()) { reportException(Error_Overflow_zero); } // if this number is zero, the result is also zero. if (isZero()) { return (NumberString *)IntegerZero; } // set of pointers for our temporary values NumberStringBase *accum = &accumBuffer; NumberStringBase *saveLeft = &saveLeftBuffer; NumberStringBase *saveRight = &saveRightBuffer; wholenumber_t digits = number_digits(); // either of these values might require rounding before starting the // operation, which might copy the values NumberString *left = checkNumber(digits); NumberString *right = other->checkNumber(digits); // calculate the probable result exponent from the two operand // exponends and the length difference. wholenumber_t calcExp = left->numberExponent - right->numberExponent; calcExp += left->digitsCount - right->digitsCount; // a negative exponent means this value will be less than // zero. If we are doing integer divide or remainder, we // // is exp < 0 and doing // or % if (calcExp < 0 && divOP != OT_DIVIDE) { // if this is integer division, the result is zero if (divOP == OT_INT_DIVIDE) { return (NumberString *)IntegerZero; } // for the remainder operation, this is the result (with suitable rounding, // of course) else { // this must be a new number value set with the current numeric values NumberString *result = left->prepareOperatorNumber(digits + 1, digits, NOROUND); result->setupNumber(); return result; } } size_t totalDigits = ((digits + 1) * 2) + 1; char *leftNum = leftBufFast; char *rightNum = rightBufFast; char *output = outBufFast; // we have automatic buffers for these that will handle typical // sizes. If larger than that, we allocate real buffer objects // and just allow them to be garbage collected at the end if (totalDigits > FAST_BUFFER) { // we can use a single buffer and chop it up leftNum = new_buffer(totalDigits * 3)->getData(); rightNum = leftNum + totalDigits; output = rightNum + totalDigits; } // make a copy of the input data into the buffers and pad the // rest of the buffer with zeros memcpy(leftNum, left->numberDigits, left->digitsCount); memset(leftNum + left->digitsCount, '\0', totalDigits - left->digitsCount); memcpy(rightNum, right->numberDigits, right->digitsCount); memset(rightNum + right->digitsCount, '\0', totalDigits - right->digitsCount); char *resultPtr = output; // copy the numberstring information as well *saveRight = *right; *saveLeft = *left; char *saveLeftPtr = NULL; char *saveRightPtr = NULL; // if this is a remainder, we need to save the pointers to // the original data if (divOP == OT_REMAINDER) { saveLeftPtr = leftNum; saveRightPtr = rightNum; // force the dividend sign to be positive. saveRight->numberSign = 1; } // the result sign is easy to compute (note, we use the saved // right sign, which might have been made positive for the // remainder operation accum->numberSign = left->numberSign * saveRight->numberSign; wholenumber_t rightPadding = 0; // we might need to pad the right number if it is shorter. // if the right is longer, we pad the left number to the same length if (saveRight->digitsCount > saveLeft->digitsCount) { // we're making the left number longer, which pads the number // because the rest of the number buffer is zeros. saveLeft->digitsCount = saveRight->digitsCount; } // the right number is shorter...we'll need to pad that out by the difference else { rightPadding = saveLeft->digitsCount - saveRight->digitsCount; // we want both numbers the same saveRight->digitsCount = saveLeft->digitsCount; } // set the new exponents using relative forms saveLeft->numberExponent = digits * 2 - saveLeft->digitsCount + 1; saveRight->numberExponent = rightPadding; wholenumber_t adjustLeft = 0; // When generating a best guess digits for result we will look // use the 1st 2 digits of the dividend (if there are 2) // we then add 1 to this DivChar to ensure than when we gues // we either guess correctly of under guess. // _______________ // aabbbbbb ) xxyyyyyyyy // // DivChar = aa + 1 // the division character is the first two digits, or // if there is only one digit, the second digit is effectively // a zero. int divChar = *rightNum * 10; if (saveRight->digitsCount > 1) { divChar += *(rightNum + 1); } // and add 1 to our division characters so that we will err on the // low side divChar++; // the count of digits in the result wholenumber_t resultDigits = 0; int thisDigit = 0; // We are now to enter 2 do forever loops, inside the loops // we test for ending conditions. and will exit the loops // when needed. This inner loop may need to break out of // both loops, if our divisor is reduced to zero(all finish // if this happens to do the no-no nad use a GOTO. // The outer loop is used to obtain all digits for the resul // We continue in this loop while the divisor has NOT been // reduced to zero and we have not reach the maximum number // of digits to be in the result (NumDigits + 1), we add // one to NumDigits so we can round if necessary. // The inner loop conputs each digits of the result and // breaks to the outer loop when the next digit of result // is found. // We compute a digit of result by continually taking best // guesses at how many times the dividend can go into the // divisor. Once The divisor becomes less than the dividend // we found this digit and we exit the inner loop. If the // divisor = dividend then we know dividend will go into // 1 more than last guess, so bump up the last guess and // exit both loops (ALL DONE !!), if neither of the above // conditions are met our last guess was low, compute a new // guess using result of last one, and go though inner loop // again. // outer loop for (; ; ) { int multiplier; // inner loop for (; ; ) { // are the two numbers now of equal length? if (saveLeft->digitsCount == saveRight->digitsCount) { // directly compare the two numbers int rc = memcmp(leftNum, rightNum, saveLeft->digitsCount); // if the left number is smaller, we're done with the inner // loop. if (rc < 0) { break; } // if the inner numbers are equal and this is not a remainder // op, we can terminate the entire loop else if (rc == 0 && divOP != OT_REMAINDER) { // divided evenly, if you add in one more to the guess *resultPtr++ = (char)(thisDigit + 1); resultDigits++; // this breaks out of both loops goto PowerDivideDone; } // either the number is greater or we're doing a remainder else { // just use one digit from the divisor for this next guess multiplier = *leftNum; } } // the left number is longer than the accumulator? else if (saveLeft->digitsCount > saveRight->digitsCount) { // calculate multiplier using the next two digits // note, since the left number is longer than the right, // we know we have at least two digis. multiplier = *leftNum * 10 + *(leftNum + 1); } // the divisor is smaller than the dividend, so we break out of the loop else { break; } // we found this digit of result, go to outer loop and finish up // processing for this digit. Compute Multiplier for actual divide multiplier = multiplier * 10 / divChar; // that is how many times will digit // of dividend go into divisor, using // the 1st 2 digits of each number // compute our Best Guess for this // digit // if this computed to zero, make it 1 if (multiplier == 0) { multiplier = 1; } // we know the divident goes into divisor at least one more time. thisDigit += multiplier; // divide the digit through and see if we guessed correctly. leftNum = subtractDivisor(leftNum, saveLeft->digitsCount, rightNum, saveRight->digitsCount, leftNum + saveLeft->digitsCount - 1, multiplier); // skip over any leading zeros leftNum = saveLeft->stripLeadingZeros(leftNum); // end of inner loop, go back and guess again !! This might have been the right guess. } // we only add zero digits if we have other digits. non-zero // digits always get added if (resultDigits != 0 || thisDigit != 0) { // add this to the result *resultPtr++ = (char) thisDigit; thisDigit = 0; resultDigits++; // we stop processing of A) the left number has been reduced // to zero or B) The result has reached our digits limit. if (*leftNum == '\0' || resultDigits > digits) { break; } } // we have different termination rules for int divide and remainder operations. if (divOP != OT_DIVIDE) { // have we generated all of the integer digits yet? // then we are done. if (calcExp <= 0) { break; } } // Was number reduced to zero? We divided evenly if (saveLeft->digitsCount == 1 && *leftNum == '\0') { break; } // we're not done dividing yet, we // need to adjust expected exponent // by one to the left calcExp--; // if we are still padding the right number, use one less digit on the // next pass if (rightPadding > 0) { saveRight->digitsCount--; rightPadding--; } // we decreased the left value to to the size of the right // before starting, so we add the digits back in as we progress. else { saveLeft->digitsCount++; } } // We've ended the entire division because we've hit equality. PowerDivideDone: ; // if this is a // or % operation, the result might be bad. // This might not be expressible as a whole number because of // the relative size of the operands, or we have a result with // no integer portion if ((divOP != OT_DIVIDE) && ((calcExp >= 0 && ( resultDigits + calcExp) > digits) || (calcExp < 0 && Numerics::abs(calcExp) > resultDigits))) { reportException(divOP == OT_REMAINDER ? Error_Invalid_whole_number_rem : Error_Invalid_whole_number_intdiv); } // if we're doing a remainder operation, we've really done an integer divide to this // point and now need to figure out the remainder portion if (divOP == OT_REMAINDER) { // if we managed to generate any result digits if (resultDigits != 0) { // the left number is the remainder. If the first digit // is zero, there is no remainder if (*leftNum != 0) { // this is our result resultPtr = leftNum; // now we need to calculate the exponent, adjusting for any added zeros saveLeftPtr += left->digitsCount; saveRightPtr = resultPtr + saveLeft->digitsCount + adjustLeft; accum->numberExponent = left->numberExponent - (saveRightPtr - saveLeftPtr); // the result length is the remaining digits count accum->digitsCount = saveLeft->digitsCount; } // we have a zero result, just return a zero else { return (NumberString *)IntegerZero; } } // no digits in result, remainder is the left number (this) else { // we return a copy of the left number NumberString *result = clone(); result->setupNumber(); return result; } } // this is a real division (but possibly integer division) so we need to finish up the result else { // if we have some sort of result digits, set up for building the final number string if (resultDigits != 0) { resultPtr = output; accum->digitsCount = resultDigits; accum->numberExponent = calcExp; // if the result is too big, we need to round to the digits setting if (accum->digitsCount > digits) { // we shorten the length and increase the exponent by the delta accum->numberExponent += (accum->digitsCount - digits); accum->digitsCount = digits; // see if we need to round accum->mathRound(resultPtr); } // We now remove any trailing zeros in the result. leftNum = resultPtr + accum->digitsCount - 1; // NOTE: We know we have at least one non-zero digit, so this loop // will not remove the entire result while (*leftNum == 0 && accum->digitsCount > 0) { leftNum--; // changes in length must be reflected with an equal and // opposite change in exponent. accum->digitsCount--; accum->numberExponent++; } } // no digits in the result, the answer is zero. This generally // only happens with integer division. else { return(NumberString *)IntegerZero; } } // ok, accum is the number data, resultPtr is the result data NumberString *result = new (accum->digitsCount) NumberString (accum->digitsCount); result->digitsCount = accum->digitsCount; result->numberExponent = accum->numberExponent; result->numberSign = accum->numberSign; // note, we have already rounded, so this should work without rounding now. result->adjustPrecision(resultPtr, digits); return result; }
/** * Run (or call) a CPPMethod. * * @param activity The activity we're running under. * @param method The method to run. * @param receiver The receiver object. * @param messageName * The name used to invoke the message. * @param argPtr The actual arguments. * @param count The argument count. * @param result The returned result. */ void CPPCode::run(Activity *activity, MethodClass *method, RexxObject *receiver, RexxString *messageName, RexxObject **argPtr, size_t count, ProtectedObject &result) { InternalActivationFrame frame(activity, messageName, receiver, method, argPtr, count); PCPPM methodEntry = this->cppEntry; /* get the entry point */ /* expecting an array? */ /* expecting a pointer/count pair? */ if (this->argumentCount == A_COUNT) { /* we can pass this right on */ result = (receiver->*((PCPPMC1)methodEntry))(argPtr, count); } else { if (count > argumentCount) { reportException(Error_Incorrect_method_maxarg, this->argumentCount); } // This is the temporary list of arguments RexxObject * argument_list[7]; if (count < argumentCount) /* need to pad these out? */ { // null out the argument list memset(argument_list, 0, sizeof(argument_list)); // and copy over the provided argument pointers memcpy(argument_list, argPtr, count * sizeof(RexxObject *)); // now switch the argument pointer to the temporary argPtr = &argument_list[0]; } // now we make the actual call switch (argumentCount) { case 0: /* zero */ result = (receiver->*((PCPPM0)methodEntry))(); break; case 1: result = (receiver->*((PCPPM1)methodEntry))(argPtr[0]); break; case 2: result = (receiver->*((PCPPM2)methodEntry))(argPtr[0], argPtr[1]); break; case 3: result = (receiver->*((PCPPM3)methodEntry))(argPtr[0], argPtr[1], argPtr[2]); break; case 4: result = (receiver->*((PCPPM4)methodEntry))(argPtr[0], argPtr[1], argPtr[2], argPtr[3]); break; case 5: result = (receiver->*((PCPPM5)methodEntry))(argPtr[0], argPtr[1], argPtr[2], argPtr[3], argPtr[4]); break; case 6: result = (receiver->*((PCPPM6)methodEntry))(argPtr[0], argPtr[1], argPtr[2], argPtr[3], argPtr[4], argPtr[5]); break; case 7: result = (receiver->*((PCPPM7)methodEntry))(argPtr[0], argPtr[1], argPtr[2], argPtr[3], argPtr[4], argPtr[5], argPtr[6]); break; } } }
void JSErrorHandler::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) { if (!is<ErrorEvent>(*event)) return JSEventListener::handleEvent(scriptExecutionContext, event); ASSERT(scriptExecutionContext); if (!scriptExecutionContext) return; ErrorEvent& errorEvent = downcast<ErrorEvent>(*event); JSLockHolder lock(scriptExecutionContext->vm()); JSObject* jsFunction = this->jsFunction(scriptExecutionContext); if (!jsFunction) return; JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, isolatedWorld()); if (!globalObject) return; ExecState* exec = globalObject->globalExec(); CallData callData; CallType callType = jsFunction->methodTable()->getCallData(jsFunction, callData); if (callType != CallTypeNone) { Ref<JSErrorHandler> protectedctor(*this); Event* savedEvent = globalObject->currentEvent(); globalObject->setCurrentEvent(event); MarkedArgumentBuffer args; args.append(jsStringWithCache(exec, errorEvent.message())); args.append(jsStringWithCache(exec, errorEvent.filename())); args.append(jsNumber(errorEvent.lineno())); args.append(jsNumber(errorEvent.colno())); VM& vm = globalObject->vm(); VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject); InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData); NakedPtr<Exception> exception; JSValue returnValue = scriptExecutionContext->isDocument() ? JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, jsFunction, callType, callData, globalObject, args, exception) : JSC::profiledCall(exec, JSC::ProfilingReason::Other, jsFunction, callType, callData, globalObject, args, exception); InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext); globalObject->setCurrentEvent(savedEvent); if (exception) reportException(exec, exception); else { if (returnValue.isTrue()) event->preventDefault(); } } }
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) { ASSERT(scriptExecutionContext); if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden()) return; VM& vm = scriptExecutionContext->vm(); JSLockHolder lock(vm); auto scope = DECLARE_CATCH_SCOPE(vm); // See https://dom.spec.whatwg.org/#dispatching-events spec on calling handleEvent. // "If this throws an exception, report the exception." It should not propagate the // exception. JSObject* jsFunction = this->jsFunction(scriptExecutionContext); if (!jsFunction) return; JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, *m_isolatedWorld); if (!globalObject) return; if (scriptExecutionContext->isDocument()) { JSDOMWindow* window = jsCast<JSDOMWindow*>(globalObject); if (!window->wrapped().isCurrentlyDisplayedInFrame()) return; if (wasCreatedFromMarkup() && !scriptExecutionContext->contentSecurityPolicy()->allowInlineEventHandlers(sourceURL(), sourcePosition().m_line)) return; // FIXME: Is this check needed for other contexts? ScriptController& script = window->wrapped().frame()->script(); if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused()) return; } ExecState* exec = globalObject->globalExec(); JSValue handleEventFunction = jsFunction; CallData callData; CallType callType = getCallData(handleEventFunction, callData); // If jsFunction is not actually a function, see if it implements the EventListener interface and use that if (callType == CallType::None) { handleEventFunction = jsFunction->get(exec, Identifier::fromString(exec, "handleEvent")); if (UNLIKELY(scope.exception())) { auto* exception = scope.exception(); scope.clearException(); event->target()->uncaughtExceptionInEventHandler(); reportException(exec, exception); return; } callType = getCallData(handleEventFunction, callData); } if (callType != CallType::None) { Ref<JSEventListener> protectedThis(*this); MarkedArgumentBuffer args; args.append(toJS(exec, globalObject, event)); Event* savedEvent = globalObject->currentEvent(); globalObject->setCurrentEvent(event); VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject); InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData); JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event->currentTarget()) : jsFunction; NakedPtr<JSC::Exception> exception; JSValue retval = scriptExecutionContext->isDocument() ? JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, handleEventFunction, callType, callData, thisValue, args, exception) : JSC::profiledCall(exec, JSC::ProfilingReason::Other, handleEventFunction, callType, callData, thisValue, args, exception); InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext); globalObject->setCurrentEvent(savedEvent); if (is<WorkerGlobalScope>(*scriptExecutionContext)) { auto scriptController = downcast<WorkerGlobalScope>(*scriptExecutionContext).script(); bool terminatorCausedException = (scope.exception() && isTerminatedExecutionException(scope.exception())); if (terminatorCausedException || scriptController->isTerminatingExecution()) scriptController->forbidExecution(); } if (exception) { event->target()->uncaughtExceptionInEventHandler(); reportException(exec, exception); } else { if (!retval.isUndefinedOrNull() && is<BeforeUnloadEvent>(*event)) downcast<BeforeUnloadEvent>(*event).setReturnValue(retval.toWTFString(exec)); if (m_isAttribute) { if (retval.isFalse()) event->preventDefault(); } } } }
void SystemInterpreter::restoreEnvironment( void *CurrentEnv) /* saved environment */ { char *current; /* ptr to saved environment */ size_t size; /* size of the saved space */ size_t length; /* string length */ char *begin; /* begin of saved space */ char **Environment; /* environment pointer */ char *del = NULL; /* ptr to old unused memory */ char *Env_Var_String; /* enviornment entry */ char namebufsave[256],namebufcurr[256]; char *np; int i; Environment = getEnvironment(); /* get the current environment*/ begin = current = (char *)CurrentEnv;/* get the saved space */ size = ((ENVENTRY*)current)->size; /* first read out the size */ current += sizeof(size_t); /* update the pointer */ if (chdir(current) == -1) /* restore the curr dir */ { char msg[1024]; sprintf(msg, "Error restoring current directory: %s", current); reportException(Error_System_service_service, msg); } current += strlen(current); /* update the pointer */ current++; /* jump over '\0' */ if (!putflag) { /* first change in the */ /* environment ? */ /* copy all entries to dynamic memory */ /*for all entries in the env */ for (;*Environment != NULL;Environment++) { length = strlen(*Environment)+1; /* get the size of the string */ /* and alloc space for it */ Env_Var_String = (char *)malloc(length); memcpy(Env_Var_String,*Environment,length);/* copy the string */ putenv(Env_Var_String); /* and make it part of env */ } putflag = 1; /* prevent do it again */ } /* Loop through the saved env */ /* entries and restore them */ for (;(size_t)(current-begin)<size;current+=(strlen(current)+1)) { Environment = getEnvironment(); /* get the environment */ del = NULL; np = current; /* extract the the name */ /* from the saved enviroment */ for (i=0;(*np!='=')&&(i<255);np++,i++) { memcpy(&(namebufsave[i]),np,1); /* copy the character */ } memcpy(&(namebufsave[i]),"\0",1); /* copy the terminator */ /* find the entry in the env */ for (;*Environment != NULL;Environment++) { np = *Environment; /* extract the the name */ /* from the current env */ for (i=0;(*np!='=')&&(i<255);np++,i++) { memcpy(&(namebufcurr[i]),np,1);/* copy the character */ } memcpy(&(namebufcurr[i]),"\0",1);/* copy the terminator */ if (!strcmp(namebufsave,namebufcurr)) {/* have a match ? */ del = *Environment; /* remember it for deletion */ break; /* found, so get out of here */ } } if (putenv(current) == -1) { reportException(Error_System_service_service, "Error restoring environment variable"); } if (del) /* if there was an old entry */ { free(del); /* free it */ } } }
/** * Read the program meta data and the image data from a file, with * image validation. * * @param handle The input file handle. * * @return A BufferClass instance containing the program data, or OREF_NULL * if the file is not a valid image. */ BufferClass *ProgramMetaData::read(RexxString *fileName, FILE *handle) { bool badVersion = false; size_t headerSize = getHeaderSize(); size_t readSize; // now read the control info readSize = fread((char *)this, 1, headerSize, handle); // if we could read the header, validate all of the meta information if (readSize < headerSize || !validate(badVersion)) { // if this failed because we couldn't read in the required header, or // because of the version signature, we need to raise an error now. if (readSize < headerSize || badVersion) { fclose(handle); reportException(Error_Program_unreadable_version, fileName); } // if it didn't validate, it might be because we have a unix-style "hash bang" line at the // beginning of the file. The first read in bit has a "#!", then we need to read // beyond the first linend and try again. if (fileTag[0] == '#' && fileTag[1] == '!') { // back to the start (ok, just past the hash bang) fseek(handle, 2, SEEK_SET); while (true) { if (fread(fileTag, 1, 1, handle) <= 0) { fclose(handle); return OREF_NULL; } // if we hit a newline, this is our stopping point. // NB: this works with both \n and \r\n sequences. if (fileTag[0] == '\n') { break; } // ok, try to read the control information one more time. // if this doesn't work, no point in being pushy about it. readSize = fread((char *)this, 1, headerSize, handle); // if we could read the header, validate all of the meta information if (readSize < headerSize || !validate(badVersion)) { fclose(handle); /* close the file */ // if because we couldn't read in the required header, or // because of a bad version sig, we can close now if (readSize < headerSize || badVersion) { reportException(Error_Program_unreadable_version, fileName); } return OREF_NULL; } } } } BufferClass *buffer = new_buffer(imageSize); ProtectedObject p(buffer); readSize = fread(buffer->getData(), 1, imageSize, handle); if (readSize < imageSize) { fclose(handle); reportException(Error_Program_unreadable_version, fileName); return OREF_NULL; } return buffer; }