示例#1
0
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;
}
示例#4
0
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);
}
示例#5
0
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();
}
示例#7
0
/**
 * 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);
    }
}
示例#8
0
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;
}
示例#9
0
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();
}
示例#12
0
/**
 * 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;
}
示例#15
0
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();
            }
        }
    }
}
示例#16
0
/**
 * 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);
}
示例#17
0
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();
}
示例#19
0
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       */
    }
}
示例#20
0
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;
}
示例#22
0
/**
 * 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;
        }
    }
}
示例#23
0
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();
        }
    }
}
示例#24
0
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                    */
        }
    }
}
示例#26
0
/**
 * 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;
}