Bug 514581 - ES5: fun.caller and fun.arguments must throw when fun is strict-mode code. r=jimb
This commit is contained in:
@@ -331,3 +331,4 @@ MSG_DEF(JSMSG_BAD_GET_SET_FIELD, 248, 1, JSEXN_TYPEERR, "property descripto
|
|||||||
MSG_DEF(JSMSG_BAD_PROXY_FIX, 249, 0, JSEXN_TYPEERR, "proxy was fixed while executing the handler")
|
MSG_DEF(JSMSG_BAD_PROXY_FIX, 249, 0, JSEXN_TYPEERR, "proxy was fixed while executing the handler")
|
||||||
MSG_DEF(JSMSG_INVALID_EVAL_SCOPE_ARG, 250, 0, JSEXN_EVALERR, "invalid eval scope argument")
|
MSG_DEF(JSMSG_INVALID_EVAL_SCOPE_ARG, 250, 0, JSEXN_EVALERR, "invalid eval scope argument")
|
||||||
MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS, 251, 3, JSEXN_SYNTAXERR, "{0} functions must have {1} argument{2}")
|
MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS, 251, 3, JSEXN_SYNTAXERR, "{0} functions must have {1} argument{2}")
|
||||||
|
MSG_DEF(JSMSG_THROW_TYPE_ERROR, 252, 0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them")
|
||||||
|
|||||||
@@ -1664,6 +1664,12 @@ struct JSClass {
|
|||||||
#define JSCLASS_MARK_IS_TRACE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
|
#define JSCLASS_MARK_IS_TRACE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
|
||||||
#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
|
#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
|
||||||
|
|
||||||
|
/* Additional global reserved slots, beyond those for standard prototypes. */
|
||||||
|
#define JSRESERVED_GLOBAL_SLOTS_COUNT 3
|
||||||
|
#define JSRESERVED_GLOBAL_COMPARTMENT (JSProto_LIMIT * 3)
|
||||||
|
#define JSRESERVED_GLOBAL_THIS (JSRESERVED_GLOBAL_COMPARTMENT + 1)
|
||||||
|
#define JSRESERVED_GLOBAL_THROWTYPEERROR (JSRESERVED_GLOBAL_THIS + 1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ECMA-262 requires that most constructors used internally create objects
|
* ECMA-262 requires that most constructors used internally create objects
|
||||||
* with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
|
* with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
|
||||||
@@ -1675,11 +1681,9 @@ struct JSClass {
|
|||||||
* with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
|
* with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
|
||||||
* prevously allowed, but is now an ES5 violation and thus unsupported.
|
* prevously allowed, but is now an ES5 violation and thus unsupported.
|
||||||
*/
|
*/
|
||||||
#define JSCLASS_GLOBAL_FLAGS \
|
#define JSCLASS_GLOBAL_FLAGS \
|
||||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSProto_LIMIT * 3 + 2))
|
(JSCLASS_IS_GLOBAL | \
|
||||||
|
JSCLASS_HAS_RESERVED_SLOTS(JSProto_LIMIT * 3 + JSRESERVED_GLOBAL_SLOTS_COUNT))
|
||||||
#define JSRESERVED_GLOBAL_COMPARTMENT (JSProto_LIMIT * 3)
|
|
||||||
#define JSRESERVED_GLOBAL_THIS (JSRESERVED_GLOBAL_COMPARTMENT + 1)
|
|
||||||
|
|
||||||
/* Fast access to the original value of each standard class's prototype. */
|
/* Fast access to the original value of each standard class's prototype. */
|
||||||
#define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 8)
|
#define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 8)
|
||||||
|
|||||||
116
js/src/jsfun.cpp
116
js/src/jsfun.cpp
@@ -87,6 +87,12 @@
|
|||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
|
inline JSObject *
|
||||||
|
JSObject::getThrowTypeError() const
|
||||||
|
{
|
||||||
|
return &getGlobal()->getReservedSlot(JSRESERVED_GLOBAL_THROWTYPEERROR).toObject();
|
||||||
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
js_GetArgsValue(JSContext *cx, JSStackFrame *fp, Value *vp)
|
js_GetArgsValue(JSContext *cx, JSStackFrame *fp, Value *vp)
|
||||||
{
|
{
|
||||||
@@ -1385,8 +1391,9 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
|||||||
* Function.prototype object (we use JSPROP_PERMANENT with JSPROP_SHARED
|
* Function.prototype object (we use JSPROP_PERMANENT with JSPROP_SHARED
|
||||||
* to make it appear so).
|
* to make it appear so).
|
||||||
*
|
*
|
||||||
* This code couples tightly to the attributes for lazy_function_props[]
|
* This code couples tightly to the attributes for lazyFunctionDataProps[]
|
||||||
* initializers above, and to js_SetProperty and js_HasOwnProperty.
|
* and poisonPillProps[] initializers below, and to js_SetProperty and
|
||||||
|
* js_HasOwnProperty.
|
||||||
*
|
*
|
||||||
* It's important to allow delegating objects, even though they inherit
|
* It's important to allow delegating objects, even though they inherit
|
||||||
* this getter (fun_getProperty), to override arguments, arity, caller,
|
* this getter (fun_getProperty), to override arguments, arity, caller,
|
||||||
@@ -1466,20 +1473,34 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LazyFunctionProp {
|
namespace {
|
||||||
|
|
||||||
|
struct LazyFunctionDataProp {
|
||||||
uint16 atomOffset;
|
uint16 atomOffset;
|
||||||
int8 tinyid;
|
int8 tinyid;
|
||||||
uint8 attrs;
|
uint8 attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* NB: no sentinel at the end -- use JS_ARRAY_LENGTH to bound loops. */
|
struct PoisonPillProp {
|
||||||
static LazyFunctionProp lazy_function_props[] = {
|
uint16 atomOffset;
|
||||||
{ATOM_OFFSET(arguments), FUN_ARGUMENTS, JSPROP_PERMANENT},
|
int8 tinyid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* NB: no sentinels at ends -- use JS_ARRAY_LENGTH to bound loops. */
|
||||||
|
|
||||||
|
const LazyFunctionDataProp lazyFunctionDataProps[] = {
|
||||||
{ATOM_OFFSET(arity), FUN_ARITY, JSPROP_PERMANENT},
|
{ATOM_OFFSET(arity), FUN_ARITY, JSPROP_PERMANENT},
|
||||||
{ATOM_OFFSET(caller), FUN_CALLER, JSPROP_PERMANENT},
|
|
||||||
{ATOM_OFFSET(name), FUN_NAME, JSPROP_PERMANENT},
|
{ATOM_OFFSET(name), FUN_NAME, JSPROP_PERMANENT},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Properties censored into [[ThrowTypeError]] in strict mode. */
|
||||||
|
const PoisonPillProp poisonPillProps[] = {
|
||||||
|
{ATOM_OFFSET(arguments), FUN_ARGUMENTS },
|
||||||
|
{ATOM_OFFSET(caller), FUN_CALLER },
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
fun_enumerate(JSContext *cx, JSObject *obj)
|
fun_enumerate(JSContext *cx, JSObject *obj)
|
||||||
{
|
{
|
||||||
@@ -1493,13 +1514,20 @@ fun_enumerate(JSContext *cx, JSObject *obj)
|
|||||||
if (!JS_LookupPropertyById(cx, obj, id, &v))
|
if (!JS_LookupPropertyById(cx, obj, id, &v))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (uintN i = 0; i < JS_ARRAY_LENGTH(lazy_function_props); i++) {
|
for (uintN i = 0; i < JS_ARRAY_LENGTH(lazyFunctionDataProps); i++) {
|
||||||
LazyFunctionProp &lfp = lazy_function_props[i];
|
const LazyFunctionDataProp &lfp = lazyFunctionDataProps[i];
|
||||||
id = ATOM_TO_JSID(OFFSET_TO_ATOM(cx->runtime, lfp.atomOffset));
|
id = ATOM_TO_JSID(OFFSET_TO_ATOM(cx->runtime, lfp.atomOffset));
|
||||||
if (!JS_LookupPropertyById(cx, obj, id, &v))
|
if (!JS_LookupPropertyById(cx, obj, id, &v))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uintN i = 0; i < JS_ARRAY_LENGTH(poisonPillProps); i++) {
|
||||||
|
const PoisonPillProp &p = poisonPillProps[i];
|
||||||
|
id = ATOM_TO_JSID(OFFSET_TO_ATOM(cx->runtime, p.atomOffset));
|
||||||
|
if (!JS_LookupPropertyById(cx, obj, id, &v))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1575,8 +1603,8 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uintN i = 0; i < JS_ARRAY_LENGTH(lazy_function_props); i++) {
|
for (uintN i = 0; i < JS_ARRAY_LENGTH(lazyFunctionDataProps); i++) {
|
||||||
LazyFunctionProp *lfp = &lazy_function_props[i];
|
const LazyFunctionDataProp *lfp = &lazyFunctionDataProps[i];
|
||||||
|
|
||||||
atom = OFFSET_TO_ATOM(cx->runtime, lfp->atomOffset);
|
atom = OFFSET_TO_ATOM(cx->runtime, lfp->atomOffset);
|
||||||
if (id == ATOM_TO_JSID(atom)) {
|
if (id == ATOM_TO_JSID(atom)) {
|
||||||
@@ -1594,6 +1622,37 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uintN i = 0; i < JS_ARRAY_LENGTH(poisonPillProps); i++) {
|
||||||
|
const PoisonPillProp &p = poisonPillProps[i];
|
||||||
|
|
||||||
|
atom = OFFSET_TO_ATOM(cx->runtime, p.atomOffset);
|
||||||
|
if (id == ATOM_TO_JSID(atom)) {
|
||||||
|
JS_ASSERT(!IsInternalFunctionObject(obj));
|
||||||
|
|
||||||
|
PropertyOp getter, setter;
|
||||||
|
uintN attrs = JSPROP_PERMANENT;
|
||||||
|
if (fun->isInterpreted() && fun->u.i.script->strictModeCode) {
|
||||||
|
JSObject *throwTypeError = obj->getThrowTypeError();
|
||||||
|
|
||||||
|
getter = CastAsPropertyOp(throwTypeError);
|
||||||
|
setter = CastAsPropertyOp(throwTypeError);
|
||||||
|
attrs |= JSPROP_GETTER | JSPROP_SETTER;
|
||||||
|
} else {
|
||||||
|
getter = fun_getProperty;
|
||||||
|
setter = PropertyStub;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), UndefinedValue(),
|
||||||
|
getter, setter,
|
||||||
|
attrs, JSScopeProperty::HAS_SHORTID,
|
||||||
|
p.tinyid, NULL)) {
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
*objp = obj;
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2393,20 +2452,43 @@ Function(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
|
|||||||
filename, lineno);
|
filename, lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
ThrowTypeError(JSContext *cx, uintN argc, Value *vp)
|
||||||
|
{
|
||||||
|
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
|
||||||
|
JSMSG_THROW_TYPE_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
JSObject *
|
JSObject *
|
||||||
js_InitFunctionClass(JSContext *cx, JSObject *obj)
|
js_InitFunctionClass(JSContext *cx, JSObject *obj)
|
||||||
{
|
{
|
||||||
JSObject *proto;
|
JSObject *proto = js_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,
|
||||||
JSFunction *fun;
|
NULL, function_methods, NULL, NULL);
|
||||||
|
|
||||||
proto = js_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,
|
|
||||||
NULL, function_methods, NULL, NULL);
|
|
||||||
if (!proto)
|
if (!proto)
|
||||||
return NULL;
|
return NULL;
|
||||||
fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);
|
|
||||||
|
JSFunction *fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);
|
||||||
if (!fun)
|
if (!fun)
|
||||||
return NULL;
|
return NULL;
|
||||||
fun->u.i.script = JSScript::emptyScript();
|
fun->u.i.script = JSScript::emptyScript();
|
||||||
|
|
||||||
|
if (obj->getClass()->flags & JSCLASS_IS_GLOBAL) {
|
||||||
|
/* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
|
||||||
|
JSObject *throwTypeError =
|
||||||
|
js_NewFunction(cx, NULL, reinterpret_cast<Native>(ThrowTypeError), 0,
|
||||||
|
JSFUN_FAST_NATIVE, obj, NULL);
|
||||||
|
if (!throwTypeError)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
JS_ALWAYS_TRUE(js_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_THROWTYPEERROR,
|
||||||
|
ObjectValue(*throwTypeError)));
|
||||||
|
}
|
||||||
|
|
||||||
return proto;
|
return proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -349,6 +349,10 @@ IsFunctionObject(const js::Value &v, JSObject **funobj)
|
|||||||
(JS_ASSERT((funobj)->isFunction()), \
|
(JS_ASSERT((funobj)->isFunction()), \
|
||||||
(JSFunction *) (funobj)->getPrivate())
|
(JSFunction *) (funobj)->getPrivate())
|
||||||
|
|
||||||
|
extern JSFunction *
|
||||||
|
js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
|
||||||
|
uintN flags, JSObject *parent, JSAtom *atom);
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -364,6 +368,9 @@ IsInternalFunctionObject(JSObject *funobj)
|
|||||||
return funobj == fun && (fun->flags & JSFUN_LAMBDA) && !funobj->getParent();
|
return funobj == fun && (fun->flags & JSFUN_LAMBDA) && !funobj->getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern JSString *
|
||||||
|
fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
extern JSObject *
|
extern JSObject *
|
||||||
@@ -372,10 +379,6 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj);
|
|||||||
extern JSObject *
|
extern JSObject *
|
||||||
js_InitArgumentsClass(JSContext *cx, JSObject *obj);
|
js_InitArgumentsClass(JSContext *cx, JSObject *obj);
|
||||||
|
|
||||||
extern JSFunction *
|
|
||||||
js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
|
|
||||||
uintN flags, JSObject *parent, JSAtom *atom);
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
js_TraceFunction(JSTracer *trc, JSFunction *fun);
|
js_TraceFunction(JSTracer *trc, JSFunction *fun);
|
||||||
|
|
||||||
@@ -555,11 +558,4 @@ js_fun_apply(JSContext *cx, uintN argc, js::Value *vp);
|
|||||||
extern JSBool
|
extern JSBool
|
||||||
js_fun_call(JSContext *cx, uintN argc, js::Value *vp);
|
js_fun_call(JSContext *cx, uintN argc, js::Value *vp);
|
||||||
|
|
||||||
|
|
||||||
namespace js {
|
|
||||||
|
|
||||||
extern JSString *
|
|
||||||
fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent);
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif /* jsfun_h___ */
|
#endif /* jsfun_h___ */
|
||||||
|
|||||||
@@ -6046,9 +6046,9 @@ JSObject::wrappedObject(JSContext *cx) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSObject *
|
JSObject *
|
||||||
JSObject::getGlobal()
|
JSObject::getGlobal() const
|
||||||
{
|
{
|
||||||
JSObject *obj = this;
|
JSObject *obj = const_cast<JSObject *>(this);
|
||||||
while (JSObject *parent = obj->getParent())
|
while (JSObject *parent = obj->getParent())
|
||||||
obj = parent;
|
obj = parent;
|
||||||
return obj;
|
return obj;
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ struct JSObject {
|
|||||||
parent = newParent;
|
parent = newParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject *getGlobal();
|
JSObject *getGlobal() const;
|
||||||
|
|
||||||
void *getPrivate() const {
|
void *getPrivate() const {
|
||||||
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
|
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
|
||||||
@@ -739,6 +739,8 @@ struct JSObject {
|
|||||||
|
|
||||||
JS_FRIEND_API(JSCompartment *) getCompartment(JSContext *cx);
|
JS_FRIEND_API(JSCompartment *) getCompartment(JSContext *cx);
|
||||||
|
|
||||||
|
inline JSObject *getThrowTypeError() const;
|
||||||
|
|
||||||
void swap(JSObject *obj);
|
void swap(JSObject *obj);
|
||||||
|
|
||||||
inline bool canHaveMethodBarrier() const;
|
inline bool canHaveMethodBarrier() const;
|
||||||
|
|||||||
@@ -1000,13 +1000,25 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We can probably use the immutable empty script singleton, just
|
* We can probably use the immutable empty script singleton, just
|
||||||
* one hard case (nupvars != 0) may stand in our way.
|
* two hard cases (nupvars != 0, strict mode code) may stand in our
|
||||||
|
* way.
|
||||||
*/
|
*/
|
||||||
JSScript *empty = JSScript::emptyScript();
|
JSScript *empty = JSScript::emptyScript();
|
||||||
|
|
||||||
if (cg->flags & TCF_IN_FUNCTION) {
|
if (cg->flags & TCF_IN_FUNCTION) {
|
||||||
fun = cg->fun;
|
fun = cg->fun;
|
||||||
JS_ASSERT(FUN_INTERPRETED(fun) && !FUN_SCRIPT(fun));
|
JS_ASSERT(fun->isInterpreted() && !FUN_SCRIPT(fun));
|
||||||
|
if (cg->flags & TCF_STRICT_MODE_CODE) {
|
||||||
|
/*
|
||||||
|
* We can't use a script singleton for empty strict mode
|
||||||
|
* functions because they have poison-pill caller and
|
||||||
|
* arguments properties:
|
||||||
|
*
|
||||||
|
* function strict() { "use strict"; }
|
||||||
|
* strict.caller; // calls [[ThrowTypeError]] function
|
||||||
|
*/
|
||||||
|
goto skip_empty;
|
||||||
|
}
|
||||||
if (fun->u.i.nupvars != 0) {
|
if (fun->u.i.nupvars != 0) {
|
||||||
/*
|
/*
|
||||||
* FIXME: upvar uses that were all optimized away may leave
|
* FIXME: upvar uses that were all optimized away may leave
|
||||||
|
|||||||
76
js/src/tests/ecma_5/Function/function-caller.js
Normal file
76
js/src/tests/ecma_5/Function/function-caller.js
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/licenses/publicdomain/
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gTestfile = 'function-caller.js';
|
||||||
|
var BUGNUMBER = 514581;
|
||||||
|
var summary = "Function.prototype.caller should throw a TypeError for " +
|
||||||
|
"strict-mode functions";
|
||||||
|
|
||||||
|
print(BUGNUMBER + ": " + summary);
|
||||||
|
|
||||||
|
/**************
|
||||||
|
* BEGIN TEST *
|
||||||
|
**************/
|
||||||
|
|
||||||
|
// behavior
|
||||||
|
|
||||||
|
function expectTypeError(fun)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fun();
|
||||||
|
throw new Error("didn't throw");
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
assertEq(e instanceof TypeError, true,
|
||||||
|
"expected TypeError calling function" +
|
||||||
|
("name" in fun ? " " + fun.name : "") + ", instead got: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bar() { "use strict"; }
|
||||||
|
expectTypeError(function barCaller() { bar.caller; });
|
||||||
|
|
||||||
|
function baz() { "use strict"; return 17; }
|
||||||
|
expectTypeError(function bazCaller() { baz.caller; });
|
||||||
|
|
||||||
|
|
||||||
|
// accessor identity
|
||||||
|
|
||||||
|
function strictMode() { "use strict"; return 42; }
|
||||||
|
var canonicalTTE = Object.getOwnPropertyDescriptor(strictMode, "caller").get;
|
||||||
|
|
||||||
|
var barCaller = Object.getOwnPropertyDescriptor(bar, "caller");
|
||||||
|
assertEq("get" in barCaller, true);
|
||||||
|
assertEq("set" in barCaller, true);
|
||||||
|
assertEq(barCaller.get, canonicalTTE);
|
||||||
|
assertEq(barCaller.set, canonicalTTE);
|
||||||
|
|
||||||
|
var barArguments = Object.getOwnPropertyDescriptor(bar, "arguments");
|
||||||
|
assertEq("get" in barArguments, true);
|
||||||
|
assertEq("set" in barArguments, true);
|
||||||
|
assertEq(barArguments.get, canonicalTTE);
|
||||||
|
assertEq(barArguments.set, canonicalTTE);
|
||||||
|
|
||||||
|
var bazCaller = Object.getOwnPropertyDescriptor(baz, "caller");
|
||||||
|
assertEq("get" in bazCaller, true);
|
||||||
|
assertEq("set" in bazCaller, true);
|
||||||
|
assertEq(bazCaller.get, canonicalTTE);
|
||||||
|
assertEq(bazCaller.set, canonicalTTE);
|
||||||
|
|
||||||
|
var bazArguments = Object.getOwnPropertyDescriptor(baz, "arguments");
|
||||||
|
assertEq("get" in bazArguments, true);
|
||||||
|
assertEq("set" in bazArguments, true);
|
||||||
|
assertEq(bazArguments.get, canonicalTTE);
|
||||||
|
assertEq(bazArguments.set, canonicalTTE);
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(true, true);
|
||||||
|
|
||||||
|
print("All tests passed!");
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
url-prefix ../../jsreftest.html?test=ecma_5/Function/
|
url-prefix ../../jsreftest.html?test=ecma_5/Function/
|
||||||
script 15.3.4.3-01.js
|
script 15.3.4.3-01.js
|
||||||
|
script function-caller.js
|
||||||
|
|||||||
Reference in New Issue
Block a user