bool
GlobalObject::getSelfHostedFunction(JSContext *cx, HandleAtom selfHostedName, HandleAtom name,
                                    unsigned nargs, MutableHandleValue funVal)
{
    RootedId shId(cx, AtomToId(selfHostedName));
    RootedObject holder(cx, cx->global()->intrinsicsHolder());

    if (HasDataProperty(cx, holder, shId, funVal.address()))
        return true;

    if (!cx->runtime()->maybeWrappedSelfHostedFunction(cx, shId, funVal))
        return false;
    if (!funVal.isUndefined())
        return true;

    JSFunction *fun = NewFunction(cx, NullPtr(), nullptr, nargs, JSFunction::INTERPRETED_LAZY,
                                  holder, name, JSFunction::ExtendedFinalizeKind, SingletonObject);
    if (!fun)
        return false;
    fun->setIsSelfHostedBuiltin();
    fun->setExtendedSlot(0, StringValue(selfHostedName));
    funVal.setObject(*fun);

    return JSObject::defineGeneric(cx, holder, shId, funVal, nullptr, nullptr, 0);
}
bool
ChromeObjectWrapper::get(JSContext *cx, HandleObject wrapper,
                         HandleObject receiver, HandleId id,
                         MutableHandleValue vp)
{
    assertEnteredPolicy(cx, wrapper, id);
    vp.setUndefined();
    JSPropertyDescriptor desc;
    // Only call through to the get trap on the underlying object if we're
    // allowed to see the property, and if what we'll find is not on a standard
    // prototype.
    if (AllowedByBase(cx, wrapper, id, js::Wrapper::GET) &&
        !PropIsFromStandardPrototype(cx, wrapper, id))
    {
        // Call the get trap.
        if (!ChromeObjectWrapperBase::get(cx, wrapper, receiver, id, vp))
            return false;
        // If we found something, we're done.
        if (!vp.isUndefined())
            return true;
    }

    // If we have no proto, we're done.
    RootedObject wrapperProto(cx);
    if (!JS_GetPrototype(cx, wrapper, wrapperProto.address()))
        return false;
    if (!wrapperProto)
        return true;

    // Try the prototype.
    MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
    return js::GetGeneric(cx, wrapperProto, receiver, id, vp.address());
}
// ES8 rev 0c1bd3004329336774cbc90de727cd0cf5f11e93 7.3.9 GetMethod,
// reimplemented for proxy handler trap-getting to produce better error
// messages.
static bool
GetProxyTrap(JSContext* cx, HandleObject handler, HandlePropertyName name, MutableHandleValue func)
{
    // Steps 2, 5.
    if (!GetProperty(cx, handler, handler, name, func))
        return false;

    // Step 3.
    if (func.isUndefined())
        return true;

    if (func.isNull()) {
        func.setUndefined();
        return true;
    }

    // Step 4.
    if (!IsCallable(func)) {
        JSAutoByteString bytes(cx, name);
        if (!bytes)
            return false;

        JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_BAD_TRAP, bytes.ptr());
        return false;
    }

    return true;
}
Example #4
0
static EvalJSONResult
ParseEvalStringAsJSON(JSContext *cx, const mozilla::Range<const CharT> chars, MutableHandleValue rval)
{
    size_t len = chars.length();
    MOZ_ASSERT((chars[0] == '(' && chars[len - 1] == ')') ||
               (chars[0] == '[' && chars[len - 1] == ']'));

    auto jsonChars = (chars[0] == '[')
                     ? chars
                     : mozilla::Range<const CharT>(chars.start().get() + 1U, len - 2);

    JSONParser<CharT> parser(cx, jsonChars, JSONParserBase::NoError);
    if (!parser.parse(rval))
        return EvalJSON_Failure;

    return rval.isUndefined() ? EvalJSON_NotJSON : EvalJSON_Success;
}
Example #5
0
bool
ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
{
    JS_ASSERT(obj->is<ArrayObject>());

    AutoDetectInvalidation adi(cx, rval.address());

    Value argv[] = { UndefinedValue(), ObjectValue(*obj) };
    AutoValueArray ava(cx, argv, 2);
    if (!js::array_shift(cx, 0, argv))
        return false;

    // If the result is |undefined|, the array was probably empty and we
    // have to monitor the return value.
    rval.set(argv[0]);
    if (rval.isUndefined())
        types::TypeScript::Monitor(cx, rval);
    return true;
}
Example #6
0
bool
ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
{
    JS_ASSERT(obj->is<ArrayObject>());

    AutoDetectInvalidation adi(cx, rval.address());

    JS::AutoValueArray<2> argv(cx);
    argv[0].setUndefined();
    argv[1].setObject(*obj);
    if (!js::array_pop(cx, 0, argv.begin()))
        return false;

    // If the result is |undefined|, the array was probably empty and we
    // have to monitor the return value.
    rval.set(argv[0]);
    if (rval.isUndefined())
        types::TypeScript::Monitor(cx, rval);
    return true;
}
Example #7
0
bool
EvalInWindow(JSContext *cx, const nsAString &source, HandleObject scope, MutableHandleValue rval)
{
    // If we cannot unwrap we must not eval in it.
    RootedObject targetScope(cx, CheckedUnwrap(scope));
    if (!targetScope) {
        JS_ReportError(cx, "Permission denied to eval in target scope");
        return false;
    }

    // Make sure that we have a window object.
    RootedObject inner(cx, CheckedUnwrap(targetScope, /* stopAtOuter = */ false));
    nsCOMPtr<nsIGlobalObject> global;
    nsCOMPtr<nsPIDOMWindow> window;
    if (!JS_IsGlobalObject(inner) ||
        !(global = GetNativeForGlobal(inner)) ||
        !(window = do_QueryInterface(global)))
    {
        JS_ReportError(cx, "Second argument must be a window");
        return false;
    }

    nsCOMPtr<nsIScriptContext> context =
        (static_cast<nsGlobalWindow*>(window.get()))->GetScriptContext();
    if (!context) {
        JS_ReportError(cx, "Script context needed");
        return false;
    }

    nsCString filename;
    unsigned lineNo;
    if (!GetFilenameAndLineNumber(cx, filename, lineNo)) {
        // Default values for non-scripted callers.
        filename.AssignLiteral("Unknown");
        lineNo = 0;
    }

    RootedObject cxGlobal(cx, JS::CurrentGlobalOrNull(cx));
    {
        // CompileOptions must be created from the context
        // we will execute this script in.
        JSContext *wndCx = context->GetNativeContext();
        AutoCxPusher pusher(wndCx);
        JS::CompileOptions compileOptions(wndCx);
        compileOptions.setFileAndLine(filename.get(), lineNo);

        // We don't want the JS engine to automatically report
        // uncaught exceptions.
        nsJSUtils::EvaluateOptions evaluateOptions;
        evaluateOptions.setReportUncaught(false);

        nsresult rv = nsJSUtils::EvaluateString(wndCx,
                                                source,
                                                targetScope,
                                                compileOptions,
                                                evaluateOptions,
                                                rval);

        if (NS_FAILED(rv)) {
            // If there was an exception we get it as a return value, if
            // the evaluation failed for some other reason, then a default
            // exception is raised.
            MOZ_ASSERT(!JS_IsExceptionPending(wndCx),
                       "Exception should be delivered as return value.");
            if (rval.isUndefined()) {
                MOZ_ASSERT(rv == NS_ERROR_OUT_OF_MEMORY);
                return false;
            }

            // If there was an exception thrown we should set it
            // on the calling context.
            RootedValue exn(wndCx, rval);
            // First we should reset the return value.
            rval.set(UndefinedValue());

            // Then clone the exception.
            JSAutoCompartment ac(wndCx, cxGlobal);
            StackScopedCloneOptions cloneOptions;
            cloneOptions.wrapReflectors = true;
            if (StackScopedClone(wndCx, cloneOptions, &exn))
                js::SetPendingExceptionCrossContext(cx, exn);

            return false;
        }
    }

    // Let's clone the return value back to the callers compartment.
    StackScopedCloneOptions cloneOptions;
    cloneOptions.wrapReflectors = true;
    if (!StackScopedClone(cx, cloneOptions, rval)) {
        rval.set(UndefinedValue());
        return false;
    }

    return true;
}