зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1348407 - Initialize %ThrowTypeError% lazily, simplify CreateFunctionPrototype. r=jwalden
--HG-- extra : rebase_source : 6ec777eabc14b501672184aa0ffc096b741e9ec8
This commit is contained in:
Родитель
04e91897cf
Коммит
9fc2afbd44
|
@ -0,0 +1,6 @@
|
|||
if (!('oomTest' in this))
|
||||
quit();
|
||||
x = evalcx("lazy");
|
||||
oomTest(function () {
|
||||
x.eval("1");
|
||||
});
|
|
@ -116,8 +116,8 @@ AdvanceToActiveCallLinear(JSContext* cx, NonBuiltinScriptFrameIter& iter, Handle
|
|||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
ThrowTypeErrorBehavior(JSContext* cx)
|
||||
void
|
||||
js::ThrowTypeErrorBehavior(JSContext* cx)
|
||||
{
|
||||
JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_ERROR, GetErrorMessage, nullptr,
|
||||
JSMSG_THROW_TYPE_ERROR);
|
||||
|
@ -814,13 +814,6 @@ fun_trace(JSTracer* trc, JSObject* obj)
|
|||
obj->as<JSFunction>().trace(trc);
|
||||
}
|
||||
|
||||
static bool
|
||||
ThrowTypeError(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
ThrowTypeErrorBehavior(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
CreateFunctionConstructor(JSContext* cx, JSProtoKey key)
|
||||
{
|
||||
|
@ -906,51 +899,6 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
|
|||
if (!JSObject::setNewGroupUnknown(cx, &JSFunction::class_, functionProto))
|
||||
return nullptr;
|
||||
|
||||
// Set the prototype before we call NewFunctionWithProto below. This
|
||||
// ensures EmptyShape::getInitialShape can share function shapes.
|
||||
self->setPrototype(key, ObjectValue(*functionProto));
|
||||
|
||||
// Construct the unique [[%ThrowTypeError%]] function object, used only for
|
||||
// "callee" and "caller" accessors on strict mode arguments objects. (The
|
||||
// spec also uses this for "arguments" and "caller" on various functions,
|
||||
// but we're experimenting with implementing them using accessors on
|
||||
// |Function.prototype| right now.)
|
||||
//
|
||||
// Note that we can't use NewFunction here, even though we want the normal
|
||||
// Function.prototype for our proto, because we're still in the middle of
|
||||
// creating that as far as the world is concerned, so things will get all
|
||||
// confused.
|
||||
RootedFunction throwTypeError(cx,
|
||||
NewFunctionWithProto(cx, ThrowTypeError, 0, JSFunction::NATIVE_FUN,
|
||||
nullptr, nullptr, functionProto, AllocKind::FUNCTION,
|
||||
SingletonObject));
|
||||
if (!throwTypeError || !PreventExtensions(cx, throwTypeError))
|
||||
return nullptr;
|
||||
|
||||
// The "length" property of %ThrowTypeError% is non-configurable, adjust
|
||||
// the default property attributes accordingly.
|
||||
Rooted<PropertyDescriptor> nonConfigurableDesc(cx);
|
||||
nonConfigurableDesc.setAttributes(JSPROP_PERMANENT | JSPROP_IGNORE_READONLY |
|
||||
JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_VALUE);
|
||||
|
||||
RootedId lengthId(cx, NameToId(cx->names().length));
|
||||
ObjectOpResult lengthResult;
|
||||
if (!NativeDefineProperty(cx, throwTypeError, lengthId, nonConfigurableDesc, lengthResult))
|
||||
return nullptr;
|
||||
MOZ_ASSERT(lengthResult);
|
||||
|
||||
// Non-standard: Also change "name" to non-configurable. ECMAScript defines
|
||||
// %ThrowTypeError% as an anonymous function, i.e. it shouldn't actually
|
||||
// get an own "name" property. To be consistent with other built-in,
|
||||
// anonymous functions, we don't delete %ThrowTypeError%'s "name" property.
|
||||
RootedId nameId(cx, NameToId(cx->names().name));
|
||||
ObjectOpResult nameResult;
|
||||
if (!NativeDefineProperty(cx, throwTypeError, nameId, nonConfigurableDesc, nameResult))
|
||||
return nullptr;
|
||||
MOZ_ASSERT(nameResult);
|
||||
|
||||
self->setThrowTypeError(throwTypeError);
|
||||
|
||||
return functionProto;
|
||||
}
|
||||
|
||||
|
|
|
@ -796,6 +796,9 @@ FunctionHasDefaultHasInstance(JSFunction* fun, const WellKnownSymbols& symbols);
|
|||
extern bool
|
||||
fun_symbolHasInstance(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern void
|
||||
ThrowTypeErrorBehavior(JSContext* cx);
|
||||
|
||||
/*
|
||||
* Function extended with reserved slots for use by various kinds of functions.
|
||||
* Most functions do not have these extensions, but enough do that efficient
|
||||
|
|
|
@ -793,9 +793,13 @@ UnmappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId i
|
|||
if (!JSID_IS_ATOM(id, cx->names().callee))
|
||||
return true;
|
||||
|
||||
JSObject* throwTypeError = GlobalObject::getOrCreateThrowTypeError(cx, cx->global());
|
||||
if (!throwTypeError)
|
||||
return false;
|
||||
|
||||
attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER;
|
||||
getter = CastAsGetterOp(argsobj->global().getThrowTypeError());
|
||||
setter = CastAsSetterOp(argsobj->global().getThrowTypeError());
|
||||
getter = CastAsGetterOp(throwTypeError);
|
||||
setter = CastAsSetterOp(throwTypeError);
|
||||
}
|
||||
|
||||
attrs |= JSPROP_RESOLVING;
|
||||
|
|
|
@ -304,6 +304,57 @@ GlobalObject::initBuiltinConstructor(JSContext* cx, Handle<GlobalObject*> global
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ThrowTypeError(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
ThrowTypeErrorBehavior(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ JSObject*
|
||||
GlobalObject::getOrCreateThrowTypeError(JSContext* cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
Value v = global->getReservedSlot(THROWTYPEERROR);
|
||||
if (v.isObject())
|
||||
return &v.toObject();
|
||||
MOZ_ASSERT(v.isUndefined());
|
||||
|
||||
// Construct the unique [[%ThrowTypeError%]] function object, used only for
|
||||
// "callee" and "caller" accessors on strict mode arguments objects. (The
|
||||
// spec also uses this for "arguments" and "caller" on various functions,
|
||||
// but we're experimenting with implementing them using accessors on
|
||||
// |Function.prototype| right now.)
|
||||
|
||||
RootedFunction throwTypeError(cx, NewNativeFunction(cx, ThrowTypeError, 0, nullptr));
|
||||
if (!throwTypeError || !PreventExtensions(cx, throwTypeError))
|
||||
return nullptr;
|
||||
|
||||
// The "length" property of %ThrowTypeError% is non-configurable, adjust
|
||||
// the default property attributes accordingly.
|
||||
Rooted<PropertyDescriptor> nonConfigurableDesc(cx);
|
||||
nonConfigurableDesc.setAttributes(JSPROP_PERMANENT | JSPROP_IGNORE_READONLY |
|
||||
JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_VALUE);
|
||||
|
||||
RootedId lengthId(cx, NameToId(cx->names().length));
|
||||
ObjectOpResult lengthResult;
|
||||
if (!NativeDefineProperty(cx, throwTypeError, lengthId, nonConfigurableDesc, lengthResult))
|
||||
return nullptr;
|
||||
MOZ_ASSERT(lengthResult);
|
||||
|
||||
// Non-standard: Also change "name" to non-configurable. ECMAScript defines
|
||||
// %ThrowTypeError% as an anonymous function, i.e. it shouldn't actually
|
||||
// get an own "name" property. To be consistent with other built-in,
|
||||
// anonymous functions, we don't delete %ThrowTypeError%'s "name" property.
|
||||
RootedId nameId(cx, NameToId(cx->names().name));
|
||||
ObjectOpResult nameResult;
|
||||
if (!NativeDefineProperty(cx, throwTypeError, nameId, nonConfigurableDesc, nameResult))
|
||||
return nullptr;
|
||||
MOZ_ASSERT(nameResult);
|
||||
|
||||
global->setReservedSlot(THROWTYPEERROR, ObjectValue(*throwTypeError));
|
||||
return throwTypeError;
|
||||
}
|
||||
|
||||
GlobalObject*
|
||||
GlobalObject::createInternal(JSContext* cx, const Class* clasp)
|
||||
{
|
||||
|
|
|
@ -124,11 +124,6 @@ class GlobalObject : public NativeObject
|
|||
LexicalEnvironmentObject& lexicalEnvironment() const;
|
||||
GlobalScope& emptyGlobalScope() const;
|
||||
|
||||
void setThrowTypeError(JSFunction* fun) {
|
||||
MOZ_ASSERT(getSlotRef(THROWTYPEERROR).isUndefined());
|
||||
setSlot(THROWTYPEERROR, ObjectValue(*fun));
|
||||
}
|
||||
|
||||
void setOriginalEval(JSObject* evalobj) {
|
||||
MOZ_ASSERT(getSlotRef(EVAL).isUndefined());
|
||||
setSlot(EVAL, ObjectValue(*evalobj));
|
||||
|
@ -743,12 +738,7 @@ class GlobalObject : public NativeObject
|
|||
Handle<GlobalObject*> global);
|
||||
RegExpStatics* getAlreadyCreatedRegExpStatics() const;
|
||||
|
||||
JSObject* getThrowTypeError() const {
|
||||
const Value v = getReservedSlot(THROWTYPEERROR);
|
||||
MOZ_ASSERT(v.isObject(),
|
||||
"attempting to access [[ThrowTypeError]] too early");
|
||||
return &v.toObject();
|
||||
}
|
||||
static JSObject* getOrCreateThrowTypeError(JSContext* cx, Handle<GlobalObject*> global);
|
||||
|
||||
static bool isRuntimeCodeGenEnabled(JSContext* cx, Handle<GlobalObject*> global);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче