bool CrossCompartmentWrapper::call(JSContext *cx, JSObject *wrapperArg, unsigned argc, Value *vp) { RootedObject wrapper(cx, wrapperArg); RootedObject wrapped(cx, wrappedObject(wrapper)); CallArgs args = CallArgsFromVp(argc, vp); { AutoCompartment call(cx, wrapped); args.setCallee(ObjectValue(*wrapped)); if (!cx->compartment->wrap(cx, args.mutableThisv())) return false; for (size_t n = 0; n < args.length(); ++n) { if (!cx->compartment->wrap(cx, args.handleAt(n))) return false; } if (!Wrapper::call(cx, wrapper, argc, vp)) return false; } return cx->compartment->wrap(cx, args.rval()); }
bool CrossCompartmentWrapper::construct(JSContext *cx, HandleObject wrapper, const CallArgs &args) { RootedObject wrapped(cx, wrappedObject(wrapper)); { AutoCompartment call(cx, wrapped); for (size_t n = 0; n < args.length(); ++n) { if (!cx->compartment->wrap(cx, args.handleAt(n))) return false; } if (!Wrapper::construct(cx, wrapper, args)) return false; } return cx->compartment->wrap(cx, args.rval()); }
/** * Handles an assertion failure in self-hosted code just like an assertion * failure in C++ code. Information about the failure can be provided in args[0]. */ static JSBool intrinsic_AssertionFailed(JSContext *cx, unsigned argc, Value *vp) { #ifdef DEBUG CallArgs args = CallArgsFromVp(argc, vp); if (args.length() > 0) { // try to dump the informative string JSString *str = ToString<CanGC>(cx, args.handleAt(0)); if (str) { const jschar *chars = str->getChars(cx); if (chars) { fprintf(stderr, "Self-hosted JavaScript assertion info: "); JSString::dumpChars(chars, str->length()); fputc('\n', stderr); } } } #endif JS_ASSERT(false); return false; }
bool CrossCompartmentWrapper::call(JSContext *cx, HandleObject wrapper, const CallArgs &args) { RootedObject wrapped(cx, wrappedObject(wrapper)); { AutoCompartment call(cx, wrapped); args.setCallee(ObjectValue(*wrapped)); if (!cx->compartment()->wrap(cx, args.mutableThisv())) return false; for (size_t n = 0; n < args.length(); ++n) { if (!cx->compartment()->wrap(cx, args.handleAt(n))) return false; } if (!Wrapper::call(cx, wrapper, args)) return false; } return cx->compartment()->wrap(cx, args.rval()); }
static JSBool intrinsic_MakeConstructible(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); JS_ASSERT(args.length() == 2); JS_ASSERT(args[0].isObject()); JS_ASSERT(args[0].toObject().is<JSFunction>()); JS_ASSERT(args[1].isObject()); // Normal .prototype properties aren't enumerable. But for this to clone // correctly, it must be enumerable. RootedObject ctor(cx, &args[0].toObject()); if (!JSObject::defineProperty(cx, ctor, cx->names().classPrototype, args.handleAt(1), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT)) { return false; } ctor->as<JSFunction>().setIsSelfHostedConstructor(); args.rval().setUndefined(); return true; }
static JSBool Exception(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); /* * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when * called as functions, without operator new. But as we do not give * each constructor a distinct JSClass, whose .name member is used by * NewNativeClassInstance to find the class prototype, we must get the * class prototype ourselves. */ RootedObject callee(cx, &args.callee()); RootedValue protov(cx); if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &protov)) return false; if (!protov.isObject()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE, "Error"); return false; } RootedObject obj(cx, NewObjectWithGivenProto(cx, &ErrorObject::class_, &protov.toObject(), NULL)); if (!obj) return false; /* Set the 'message' property. */ RootedString message(cx); if (args.hasDefined(0)) { message = ToString<CanGC>(cx, args.handleAt(0)); if (!message) return false; args[0].setString(message); } else { message = NULL; } /* Find the scripted caller. */ NonBuiltinScriptFrameIter iter(cx); /* Set the 'fileName' property. */ RootedScript script(cx, iter.done() ? NULL : iter.script()); RootedString filename(cx); if (args.length() > 1) { filename = ToString<CanGC>(cx, args.handleAt(1)); if (!filename) return false; args[1].setString(filename); } else { filename = cx->runtime()->emptyString; if (!iter.done()) { if (const char *cfilename = script->filename()) { filename = FilenameToString(cx, cfilename); if (!filename) return false; } } } /* Set the 'lineNumber' property. */ uint32_t lineno, column = 0; if (args.length() > 2) { if (!ToUint32(cx, args[2], &lineno)) return false; } else { lineno = iter.done() ? 0 : PCToLineNumber(script, iter.pc(), &column); } int exnType = args.callee().as<JSFunction>().getExtendedSlot(0).toInt32(); if (!InitExnPrivate(cx, obj, message, filename, lineno, column, NULL, exnType)) return false; args.rval().setObject(*obj); return true; }
/* * Compile a new |RegExpShared| for the |RegExpObject|. * * Per ECMAv5 15.10.4.1, we act on combinations of (pattern, flags) as * arguments: * * RegExp, undefined => flags := pattern.flags * RegExp, _ => throw TypeError * _ => pattern := ToString(pattern) if defined(pattern) else '' * flags := ToString(flags) if defined(flags) else '' */ static bool CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args) { if (args.length() == 0) { RegExpStatics *res = cx->regExpStatics(); Rooted<JSAtom*> empty(cx, cx->runtime()->emptyString); RegExpObject *reobj = builder.build(empty, res->getFlags()); if (!reobj) return false; args.rval().setObject(*reobj); return true; } RootedValue sourceValue(cx, args[0]); /* * If we get passed in an object whose internal [[Class]] property is * "RegExp", return a new object with the same source/flags. */ if (IsObjectWithClass(sourceValue, ESClass_RegExp, cx)) { /* * Beware, sourceObj may be a (transparent) proxy to a RegExp, so only * use generic (proxyable) operations on sourceObj that do not assume * sourceObj.is<RegExpObject>(). */ RootedObject sourceObj(cx, &sourceValue.toObject()); if (args.hasDefined(1)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEWREGEXP_FLAGGED); return false; } /* * Only extract the 'flags' out of sourceObj; do not reuse the * RegExpShared since it may be from a different compartment. */ RegExpFlag flags; { RegExpGuard g(cx); if (!RegExpToShared(cx, sourceObj, &g)) return false; flags = g->getFlags(); } /* * 'toSource' is a permanent read-only property, so this is equivalent * to executing RegExpObject::getSource on the unwrapped object. */ RootedValue v(cx); if (!JSObject::getProperty(cx, sourceObj, sourceObj, cx->names().source, &v)) return false; Rooted<JSAtom*> sourceAtom(cx, &v.toString()->asAtom()); RegExpObject *reobj = builder.build(sourceAtom, flags); if (!reobj) return false; args.rval().setObject(*reobj); return true; } RootedAtom source(cx); if (sourceValue.isUndefined()) { source = cx->runtime()->emptyString; } else { /* Coerce to string and compile. */ JSString *str = ToString<CanGC>(cx, sourceValue); if (!str) return false; source = AtomizeString<CanGC>(cx, str); if (!source) return false; } RegExpFlag flags = RegExpFlag(0); if (args.hasDefined(1)) { RootedString flagStr(cx, ToString<CanGC>(cx, args.handleAt(1))); if (!flagStr) return false; args[1].setString(flagStr); if (!ParseRegExpFlags(cx, flagStr, &flags)) return false; } RootedAtom escapedSourceStr(cx, EscapeNakedForwardSlashes(cx, source)); if (!escapedSourceStr) return false; if (!js::RegExpShared::checkSyntax(cx, NULL, escapedSourceStr)) return false; RegExpStatics *res = cx->regExpStatics(); RegExpObject *reobj = builder.build(escapedSourceStr, RegExpFlag(flags | res->getFlags())); if (!reobj) return false; args.rval().setObject(*reobj); return true; }