From 154056d0448e04936d794418c71a666807db1798 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 11 Aug 2010 23:27:40 -0700 Subject: [PATCH] Bug 516255 - Fix attributes on arguments[i]: index properties on arguments should be enumerable, configurable, and writable. r=dmandelin --- js/src/jsfun.cpp | 18 ++-- .../Function/arguments-property-attributes.js | 102 ++++++++++++++++++ js/src/tests/ecma_5/Function/jstests.list | 1 + 3 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 js/src/tests/ecma_5/Function/arguments-property-attributes.js diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 88154719a3c6..f250f2fe7931 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -596,8 +596,10 @@ args_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, *objp = NULL; bool valid = false; + uintN attrs = JSPROP_SHARED; if (JSID_IS_INT(id)) { uint32 arg = uint32(JSID_TO_INT(id)); + attrs = JSPROP_ENUMERATE | JSPROP_SHARED; if (arg < obj->getArgsInitialLength() && !obj->getArgsElement(arg).isMagic(JS_ARGS_HOLE)) valid = true; } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) { @@ -609,12 +611,8 @@ args_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, } if (valid) { - /* - * XXX ECMA specs DontEnum even for indexed properties, contrary to - * other array-like objects. - */ Value tmp = UndefinedValue(); - if (!js_DefineProperty(cx, obj, id, &tmp, ArgGetter, ArgSetter, JSPROP_SHARED)) + if (!js_DefineProperty(cx, obj, id, &tmp, ArgGetter, ArgSetter, attrs)) return JS_FALSE; *objp = obj; } @@ -713,8 +711,10 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject *objp = NULL; bool valid = false; + uintN attrs = JSPROP_SHARED; if (JSID_IS_INT(id)) { uint32 arg = uint32(JSID_TO_INT(id)); + attrs = JSPROP_SHARED | JSPROP_ENUMERATE; if (arg < obj->getArgsInitialLength() && !obj->getArgsElement(arg).isMagic(JS_ARGS_HOLE)) valid = true; } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) { @@ -746,13 +746,9 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject } if (valid) { - /* - * XXX ECMA specs DontEnum even for indexed properties, contrary to - * other array-like objects. - */ Value tmp = UndefinedValue(); - if (!js_DefineProperty(cx, obj, id, &tmp, StrictArgGetter, StrictArgSetter, JSPROP_SHARED)) - return JS_FALSE; + if (!js_DefineProperty(cx, obj, id, &tmp, StrictArgGetter, StrictArgSetter, attrs)) + return false; *objp = obj; } return true; diff --git a/js/src/tests/ecma_5/Function/arguments-property-attributes.js b/js/src/tests/ecma_5/Function/arguments-property-attributes.js new file mode 100644 index 000000000000..994b97ca41e0 --- /dev/null +++ b/js/src/tests/ecma_5/Function/arguments-property-attributes.js @@ -0,0 +1,102 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'arguments-property-attributes.js'; +var BUGNUMBER = 516255; +var summary = "Attributes for properties of arguments objects"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// normal + +function args() { return arguments; } +var a = args(0, 1); + +var argProps = Object.getOwnPropertyNames(a).sort(); +assertEq(argProps.indexOf("callee") >= 0, true); +assertEq(argProps.indexOf("0") >= 0, true); +assertEq(argProps.indexOf("1") >= 0, true); +assertEq(argProps.indexOf("length") >= 0, true); + +var calleeDesc = Object.getOwnPropertyDescriptor(a, "callee"); +assertEq(calleeDesc.value, args); +assertEq(calleeDesc.writable, true); +assertEq(calleeDesc.enumerable, false); +assertEq(calleeDesc.configurable, true); + +var zeroDesc = Object.getOwnPropertyDescriptor(a, "0"); +assertEq(zeroDesc.value, 0); +assertEq(zeroDesc.writable, true); +assertEq(zeroDesc.enumerable, true); +assertEq(zeroDesc.configurable, true); + +var oneDesc = Object.getOwnPropertyDescriptor(a, "1"); +assertEq(oneDesc.value, 1); +assertEq(oneDesc.writable, true); +assertEq(oneDesc.enumerable, true); +assertEq(oneDesc.configurable, true); + +var lengthDesc = Object.getOwnPropertyDescriptor(a, "length"); +assertEq(lengthDesc.value, 2); +assertEq(lengthDesc.writable, true); +assertEq(lengthDesc.enumerable, false); +assertEq(lengthDesc.configurable, true); + + +// strict + +function strictArgs() { "use strict"; return arguments; } +var sa = strictArgs(0, 1); + +var strictArgProps = Object.getOwnPropertyNames(sa).sort(); +assertEq(strictArgProps.indexOf("callee") >= 0, true); +assertEq(strictArgProps.indexOf("caller") >= 0, true); +assertEq(strictArgProps.indexOf("0") >= 0, true); +assertEq(strictArgProps.indexOf("1") >= 0, true); +assertEq(strictArgProps.indexOf("length") >= 0, true); + +var strictCalleeDesc = Object.getOwnPropertyDescriptor(sa, "callee"); +assertEq(typeof strictCalleeDesc.get, "function"); +assertEq(typeof strictCalleeDesc.set, "function"); +assertEq(strictCalleeDesc.get, strictCalleeDesc.set); +assertEq(strictCalleeDesc.enumerable, false); +assertEq(strictCalleeDesc.configurable, false); + +var strictCallerDesc = Object.getOwnPropertyDescriptor(sa, "caller"); +assertEq(typeof strictCallerDesc.get, "function"); +assertEq(typeof strictCallerDesc.set, "function"); +assertEq(strictCallerDesc.get, strictCallerDesc.set); +assertEq(strictCallerDesc.enumerable, false); +assertEq(strictCallerDesc.configurable, false); + +var strictZeroDesc = Object.getOwnPropertyDescriptor(sa, "0"); +assertEq(strictZeroDesc.value, 0); +assertEq(strictZeroDesc.writable, true); +assertEq(strictZeroDesc.enumerable, true); +assertEq(strictZeroDesc.configurable, true); + +var strictOneDesc = Object.getOwnPropertyDescriptor(sa, "1"); +assertEq(strictOneDesc.value, 1); +assertEq(strictOneDesc.writable, true); +assertEq(strictOneDesc.enumerable, true); +assertEq(strictOneDesc.configurable, true); + +var strictLengthDesc = Object.getOwnPropertyDescriptor(sa, "length"); +assertEq(strictLengthDesc.value, 2); +assertEq(strictLengthDesc.writable, true); +assertEq(strictLengthDesc.enumerable, false); +assertEq(strictLengthDesc.configurable, true); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/ecma_5/Function/jstests.list b/js/src/tests/ecma_5/Function/jstests.list index d7dd015b591f..ecf3bc528a6a 100644 --- a/js/src/tests/ecma_5/Function/jstests.list +++ b/js/src/tests/ecma_5/Function/jstests.list @@ -3,3 +3,4 @@ script 15.3.4.3-01.js script arguments-caller-callee.js script function-caller.js script strict-arguments.js +script arguments-property-attributes.js