This commit is contained in:
Cameron Kaiser 2018-09-15 16:52:51 -07:00
parent 80646986b5
commit 389ff7a57d
3 changed files with 62 additions and 0 deletions

View File

@ -152,6 +152,19 @@ function GetIterator(obj, method) {
return iterator;
}
var _builtinCtorsCache = {__proto__: null};
function GetBuiltinConstructor(builtinName) {
var ctor = _builtinCtorsCache[builtinName] ||
(_builtinCtorsCache[builtinName] = GetBuiltinConstructorImpl(builtinName));
assert(ctor, `No builtin with name "${builtinName}" found`);
return ctor;
}
function GetBuiltinPrototype(builtinName) {
return (_builtinCtorsCache[builtinName] || GetBuiltinConstructor(builtinName)).prototype;
}
// ES6 draft 20150317 7.3.20.
function SpeciesConstructor(obj, defaultConstructor) {
// Step 1.

View File

@ -0,0 +1,13 @@
let getCtor = getSelfHostedValue('GetBuiltinConstructor');
assertEq(getCtor('Array'), Array);
let origArray = Array;
Array = function(){};
assertEq(getCtor('Array') == Array, false);
assertEq(getCtor('Array'), origArray);
let origMap = Map;
Map = function(){};
assertEq(getCtor('Map') == Map, false);
assertEq(getCtor('Map'), origMap);

View File

@ -148,6 +148,41 @@ intrinsic_IsInstanceOfBuiltin(JSContext* cx, unsigned argc, Value* vp)
return true;
}
/**
* Self-hosting intrinsic returning the original constructor for a builtin
* the name of which is the first and only argument.
*
* The return value is guaranteed to be the original constructor even if
* content code changed the named binding on the global object.
*
* This intrinsic shouldn't be called directly. Instead, the
* `GetBuiltinConstructor` and `GetBuiltinPrototype` helper functions in
* Utilities.js should be used, as they cache results, improving performance.
*/
static bool
intrinsic_GetBuiltinConstructor(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
RootedString str(cx, args[0].toString());
JSAtom* atom;
if (str->isAtom()) {
atom = &str->asAtom();
} else {
atom = AtomizeString(cx, str);
if (!atom)
return false;
}
RootedId id(cx, AtomToId(atom));
JSProtoKey key = JS_IdToProtoKey(cx, id);
MOZ_ASSERT(key != JSProto_Null);
RootedObject ctor(cx);
if (!GetBuiltinConstructor(cx, key, &ctor))
return false;
args.rval().setObject(*ctor);
return true;
}
static bool
intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp)
{
@ -1467,6 +1502,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("ToPropertyKey", intrinsic_ToPropertyKey, 1,0),
JS_INLINABLE_FN("IsCallable", intrinsic_IsCallable, 1,0, IntrinsicIsCallable),
JS_FN("IsConstructor", intrinsic_IsConstructor, 1,0),
JS_FN("GetBuiltinConstructorImpl", intrinsic_GetBuiltinConstructor, 1,0),
JS_FN("OwnPropertyKeys", intrinsic_OwnPropertyKeys, 1,0),
JS_FN("ThrowRangeError", intrinsic_ThrowRangeError, 4,0),
JS_FN("ThrowTypeError", intrinsic_ThrowTypeError, 4,0),