# HG changeset patch # Parent 229801d17f7e24e2cb5ad368b553994f1482d4bb # User ziyunfei <446240525@qq.com> Bug 1038545 - Coerce the argument passed to Object.keys using ToObject. r=till diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -834,58 +834,22 @@ js::obj_getOwnPropertyDescriptor(JSConte if (!GetFirstArgumentAsObject(cx, args, "Object.getOwnPropertyDescriptor", &obj)) return false; RootedId id(cx); if (!ValueToId(cx, args.get(1), &id)) return false; return GetOwnPropertyDescriptor(cx, obj, id, args.rval()); } -// ES6 draft rev25 (2014/05/22) 19.1.2.14 Object.keys(O) +// ES6 draft rev27 (2014/08/24) 19.1.2.14 Object.keys(O) static bool obj_keys(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - - // Steps 1-2. - RootedObject obj(cx); - if (!GetFirstArgumentAsObject(cx, args, "Object.keys", &obj)) - return false; - - // Steps 3-10. Since JSITER_SYMBOLS and JSITER_HIDDEN are not passed, - // GetPropertyNames performs the type check in step 10.c. and the - // [[Enumerable]] check specified in step 10.c.iii. - AutoIdVector props(cx); - if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props)) - return false; - - AutoValueVector namelist(cx); - if (!namelist.reserve(props.length())) - return false; - for (size_t i = 0, len = props.length(); i < len; i++) { - jsid id = props[i]; - JSString *str; - if (JSID_IS_STRING(id)) { - str = JSID_TO_STRING(id); - } else { - str = Int32ToString(cx, JSID_TO_INT(id)); - if (!str) - return false; - } - namelist.infallibleAppend(StringValue(str)); - } - - // Step 11. - MOZ_ASSERT(props.length() <= UINT32_MAX); - JSObject *aobj = NewDenseCopiedArray(cx, uint32_t(namelist.length()), namelist.begin()); - if (!aobj) - return false; - - args.rval().setObject(*aobj); - return true; + return GetOwnPropertyKeys(cx, args, JSITER_OWNONLY); } /* ES6 draft 15.2.3.16 */ static bool obj_is(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); diff --git a/js/src/tests/ecma_6/Object/keys.js b/js/src/tests/ecma_6/Object/keys.js new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_6/Object/keys.js @@ -0,0 +1,23 @@ +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +var BUGNUMBER = 1038545; +var summary = "Coerce the argument passed to Object.keys using ToObject"; +print(BUGNUMBER + ": " + summary); + +assertThrowsInstanceOf(() => Object.keys(), TypeError); +assertThrowsInstanceOf(() => Object.keys(undefined), TypeError); +assertThrowsInstanceOf(() => Object.keys(null), TypeError); + +assertDeepEq(Object.keys(1), []); +assertDeepEq(Object.keys(true), []); +if (typeof Symbol === "function") { + assertDeepEq(Object.keys(Symbol("foo")), []); +} + +assertDeepEq(Object.keys("foo"), ["0", "1", "2"]); + +if (typeof reportCompare === "function") + reportCompare(true, true);