author | Tom Schuster <evilpies@gmail.com> |
Sun, 11 Jan 2015 21:21:35 +0100 | |
changeset 223165 | 93c6ac70dc60ec1442c97ee4d22648c3551286fe |
parent 223164 | 86f23a66df4a6c5bccac46ffeb1be7801101af61 |
child 223166 | 010693d8f889809b9415019f0beb0845bc52b6f7 |
push id | 53842 |
push user | evilpies@gmail.com |
push date | Sun, 11 Jan 2015 21:43:00 +0000 |
treeherder | mozilla-inbound@93c6ac70dc60 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | till |
bugs | 1119217 |
milestone | 37.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/builtin/TypedArray.js +++ b/js/src/builtin/TypedArray.js @@ -1,12 +1,28 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// ES6 draft rev30 (2014/12/24) 22.2.3.6 %TypedArray%.prototype.entries() +function TypedArrayEntries() { + // Step 1. + var O = this; + + // Step 2-3. + if (!IsObject(O) || !IsTypedArray(O)) { + return callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayEntries"); + } + + // Step 4-6. Bug 1101256: detachment checks + + // Step 7. + return CreateArrayIterator(O, ITEM_KIND_KEY_AND_VALUE); +} + // ES6 draft rev30 (2014/12/24) 22.2.3.7 %TypedArray%.prototype.every(callbackfn[, thisArg]). function TypedArrayEvery(callbackfn, thisArg = undefined) { // This function is not generic. if (!IsObject(this) || !IsTypedArray(this)) { return callFunction(CallTypedArrayMethodIfWrapped, this, callbackfn, thisArg, "TypedArrayEvery"); } @@ -246,16 +262,32 @@ function TypedArrayJoin(separator) { // Step 13.e. R = S + next; } // Step 14. return R; } +// ES6 draft rev30 (2014/12/24) 22.2.3.15 %TypedArray%.prototype.keys() +function TypedArrayKeys() { + // Step 1. + var O = this; + + // Step 2-3. + if (!IsObject(O) || !IsTypedArray(O)) { + return callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayKeys"); + } + + // Step 4-6. Bug 1101256: detachment checks + + // Step 7. + return CreateArrayIterator(O, ITEM_KIND_KEY); +} + // ES6 draft rev29 (2014/12/06) 22.2.3.16 %TypedArray%.prototype.lastIndexOf(searchElement [,fromIndex]). function TypedArrayLastIndexOf(searchElement, fromIndex = undefined) { // This function is not generic. if (!IsObject(this) || !IsTypedArray(this)) { return callFunction(CallTypedArrayMethodIfWrapped, this, searchElement, fromIndex, "TypedArrayLastIndexOf"); } @@ -438,16 +470,32 @@ function TypedArraySome(callbackfn, this if (testResult) return true; } // Step 10. return false; } +// ES6 draft rev30 (2014/12/24) 22.2.3.30 %TypedArray%.prototype.values() +function TypedArrayValues() { + // Step 1. + var O = this; + + // Step 2-3. + if (!IsObject(O) || !IsTypedArray(O)) { + return callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayValues"); + } + + // Step 4-6. Bug 1101256: detachment checks + + // Step 7. + return CreateArrayIterator(O, ITEM_KIND_VALUE); +} + // Proposed for ES7: // https://github.com/tc39/Array.prototype.includes/blob/7c023c19a0/spec.md function TypedArrayIncludes(searchElement, fromIndex = 0) { // This function is not generic. if (!IsObject(this) || !IsTypedArray(this)) { return callFunction(CallTypedArrayMethodIfWrapped, this, searchElement, fromIndex, "TypedArrayIncludes"); }
new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_6/TypedArray/entries.js @@ -0,0 +1,49 @@ +const constructors = [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array +]; + +for (var constructor of constructors) { + assertEq(constructor.prototype.entries.length, 0); + assertEq(constructor.prototype.entries.name, "entries"); + + assertDeepEq([...new constructor(0).entries()], []); + assertDeepEq([...new constructor(1).entries()], [[0, 0]]); + assertDeepEq([...new constructor(2).entries()], [[0, 0], [1, 0]]); + assertDeepEq([...new constructor([15]).entries()], [[0, 15]]); + + var arr = new constructor([1, 2, 3]); + var iterator = arr.entries(); + assertDeepEq(iterator.next(), {value: [0, 1], done: false}); + assertDeepEq(iterator.next(), {value: [1, 2], done: false}); + assertDeepEq(iterator.next(), {value: [2, 3], done: false}); + assertDeepEq(iterator.next(), {value: undefined, done: true}); + + // Called from other globals. + if (typeof newGlobal === "function") { + var entries = newGlobal()[constructor.name].prototype.entries; + assertDeepEq([...entries.call(new constructor(2))], [[0, 0], [1, 0]]); + arr = newGlobal()[constructor.name](2); + assertEq([...constructor.prototype.entries.call(arr)].toString(), "0,0,1,0"); + } + + // Throws if `this` isn't a TypedArray. + var invalidReceivers = [undefined, null, 1, false, "", Symbol(), [], {}, /./]; + invalidReceivers.forEach(invalidReceiver => { + assertThrowsInstanceOf(() => { + constructor.prototype.entries.call(invalidReceiver); + }, TypeError, "Assert that entries fails if this value is not a TypedArray"); + }); + // FIXME: Should throw exception if `this` is a proxy, see bug 1115361. + constructor.prototype.entries.call(new Proxy(new constructor(), {})); +} + +if (typeof reportCompare === "function") + reportCompare(true, true);
new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_6/TypedArray/keys.js @@ -0,0 +1,49 @@ +const constructors = [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array +]; + +for (var constructor of constructors) { + assertEq(constructor.prototype.keys.length, 0); + assertEq(constructor.prototype.keys.name, "keys"); + + assertDeepEq([...new constructor(0).keys()], []); + assertDeepEq([...new constructor(1).keys()], [0]); + assertDeepEq([...new constructor(2).keys()], [0, 1]); + assertDeepEq([...new constructor([15]).keys()], [0]); + + var arr = new constructor([1, 2, 3]); + var iterator = arr.keys(); + assertDeepEq(iterator.next(), {value: 0, done: false}); + assertDeepEq(iterator.next(), {value: 1, done: false}); + assertDeepEq(iterator.next(), {value: 2, done: false}); + assertDeepEq(iterator.next(), {value: undefined, done: true}); + + // Called from other globals. + if (typeof newGlobal === "function") { + var keys = newGlobal()[constructor.name].prototype.keys; + assertDeepEq([...keys.call(new constructor(2))], [0, 1]); + arr = newGlobal()[constructor.name](2); + assertEq([...constructor.prototype.keys.call(arr)].toString(), "0,1"); + } + + // Throws if `this` isn't a TypedArray. + var invalidReceivers = [undefined, null, 1, false, "", Symbol(), [], {}, /./]; + invalidReceivers.forEach(invalidReceiver => { + assertThrowsInstanceOf(() => { + constructor.prototype.keys.call(invalidReceiver); + }, TypeError, "Assert that keys fails if this value is not a TypedArray"); + }); + // FIXME: Should throw exception if `this` is a proxy, see bug 1115361. + constructor.prototype.keys.call(new Proxy(new constructor(), {})); +} + +if (typeof reportCompare === "function") + reportCompare(true, true);
new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_6/TypedArray/values.js @@ -0,0 +1,50 @@ +const constructors = [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array +]; + +for (var constructor of constructors) { + assertEq(constructor.prototype.values.length, 0); + assertEq(constructor.prototype.values.name, "values"); + assertEq(constructor.prototype.values, constructor.prototype[Symbol.iterator]); + + assertDeepEq([...new constructor(0).values()], []); + assertDeepEq([...new constructor(1).values()], [0]); + assertDeepEq([...new constructor(2).values()], [0, 0]); + assertDeepEq([...new constructor([15]).values()], [15]); + + var arr = new constructor([1, 2, 3]); + var iterator = arr.values(); + assertDeepEq(iterator.next(), {value: 1, done: false}); + assertDeepEq(iterator.next(), {value: 2, done: false}); + assertDeepEq(iterator.next(), {value: 3, done: false}); + assertDeepEq(iterator.next(), {value: undefined, done: true}); + + // Called from other globals. + if (typeof newGlobal === "function") { + var values = newGlobal()[constructor.name].prototype.values; + assertDeepEq([...values.call(new constructor([42, 36]))], [42, 36]); + arr = newGlobal()[constructor.name]([42, 36]); + assertEq([...constructor.prototype.values.call(arr)].toString(), "42,36"); + } + + // Throws if `this` isn't a TypedArray. + var invalidReceivers = [undefined, null, 1, false, "", Symbol(), [], {}, /./]; + invalidReceivers.forEach(invalidReceiver => { + assertThrowsInstanceOf(() => { + constructor.prototype.values.call(invalidReceiver); + }, TypeError, "Assert that values fails if this value is not a TypedArray"); + }); + // FIXME: Should throw exception if `this` is a proxy, see bug 1115361. + constructor.prototype.values.call(new Proxy(new constructor(), {})); +} + +if (typeof reportCompare === "function") + reportCompare(true, true);
--- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -206,16 +206,17 @@ macro(unsized, unsized, "unsized") \ macro(unwatch, unwatch, "unwatch") \ macro(url, url, "url") \ macro(usage, usage, "usage") \ macro(useGrouping, useGrouping, "useGrouping") \ macro(useAsm, useAsm, "use asm") \ macro(useStrict, useStrict, "use strict") \ macro(value, value, "value") \ + macro(values, values, "values") \ macro(valueOf, valueOf, "valueOf") \ macro(var, var, "var") \ macro(variable, variable, "variable") \ macro(void0, void0, "(void 0)") \ macro(watch, watch, "watch") \ macro(WeakSet_add, WeakSet_add, "WeakSet_add") \ macro(writable, writable, "writable") \ macro(w, w, "w") \
--- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -254,17 +254,16 @@ class TypedArrayObjectTemplate : public RootedFunction fun(cx); fun = NewFunction(cx, NullPtr(), ArrayBufferObject::createTypedArrayFromBuffer<NativeType>, 0, JSFunction::NATIVE_FUN, cx->global(), NullPtr()); if (!fun) return false; cx->global()->setCreateArrayFromBuffer<NativeType>(fun); - return true; } static inline const Class *instanceClass() { return TypedArrayObject::classForType(ArrayTypeID()); } @@ -690,16 +689,44 @@ TypedArrayObjectTemplate<T>::fromArray(J bool TypedArrayConstructor(JSContext *cx, unsigned argc, Value *vp) { JS_ReportError(cx, "%%TypedArray%% calling/constructing not implemented yet"); return false; } +static bool +FinishTypedArrayInit(JSContext *cx, HandleObject ctor, HandleObject proto) +{ + // Define `values` and `@@iterator` manually, because they are supposed to be the same object. + RootedId name(cx, NameToId(cx->names().values)); + RootedFunction fun(cx, GetSelfHostedFunction(cx, "TypedArrayValues", name, 0)); + if (!fun) + return false; + + RootedValue funValue(cx, ObjectValue(*fun)); + if (!JSObject::defineProperty(cx, proto, cx->names().values, funValue, nullptr, nullptr, 0)) + return false; + +#ifdef JS_HAS_SYMBOLS + RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator)); + if (!JSObject::defineGeneric(cx, proto, iteratorId, funValue, nullptr, nullptr, 0)) + return false; +#else + if (!JSObject::defineProperty(cx, proto, cx->names().std_iterator, funValue, nullptr, + nullptr, 0)) + { + return false; + } +#endif + + return true; +} + /* * These next 3 functions are brought to you by the buggy GCC we use to build * B2G ICS. Older GCC versions have a bug in which they fail to compile * reinterpret_casts of templated functions with the message: "insufficient * contextual information to determine type". JS_PSG needs to * reinterpret_cast<JSPropertyOp>, so this causes problems for us here. * * We could restructure all this code to make this nicer, but since ICS isn't @@ -774,31 +801,35 @@ TypedArrayObject::subarray(JSContext *cx { CallArgs args = CallArgsFromVp(argc, vp); return CallNonGenericMethod<TypedArrayObject::is, TypedArrayMethods<TypedArrayObject>::subarray>(cx, args); } /* static */ const JSFunctionSpec TypedArrayObject::protoFunctions[] = { - JS_SELF_HOSTED_SYM_FN(iterator, "ArrayValues", 0, 0), \ JS_FN("subarray", TypedArrayObject::subarray, 2, 0), JS_FN("set", TypedArrayObject::set, 2, 0), JS_FN("copyWithin", TypedArrayObject::copyWithin, 2, 0), JS_SELF_HOSTED_FN("every", "TypedArrayEvery", 2, 0), JS_SELF_HOSTED_FN("fill", "TypedArrayFill", 3, 0), JS_SELF_HOSTED_FN("find", "TypedArrayFind", 2, 0), JS_SELF_HOSTED_FN("findIndex", "TypedArrayFindIndex", 2, 0), JS_SELF_HOSTED_FN("indexOf", "TypedArrayIndexOf", 2, 0), JS_SELF_HOSTED_FN("join", "TypedArrayJoin", 1, 0), JS_SELF_HOSTED_FN("lastIndexOf", "TypedArrayLastIndexOf", 2, 0), JS_SELF_HOSTED_FN("reduce", "TypedArrayReduce", 1, 0), JS_SELF_HOSTED_FN("reduceRight", "TypedArrayReduceRight", 1, 0), JS_SELF_HOSTED_FN("reverse", "TypedArrayReverse", 0, 0), JS_SELF_HOSTED_FN("some", "TypedArraySome", 2, 0), + JS_SELF_HOSTED_FN("entries", "TypedArrayEntries", 0, 0), + JS_SELF_HOSTED_FN("keys", "TypedArrayKeys", 0, 0), + // Both of these are actually defined to the same object in FinishTypedArrayInit. + JS_SELF_HOSTED_FN("values", "TypedArrayValues", 0, JSPROP_DEFINE_LATE), + JS_SELF_HOSTED_SYM_FN(iterator, "TypedArrayValues", 0, JSPROP_DEFINE_LATE), #ifdef NIGHTLY_BUILD JS_SELF_HOSTED_FN("includes", "TypedArrayIncludes", 2, 0), #endif JS_FS_END }; /* static */ const JSFunctionSpec TypedArrayObject::staticFunctions[] = { @@ -829,17 +860,17 @@ TypedArrayObject::sharedTypedArrayProtot nullptr, /* construct */ nullptr, /* trace */ { GenericCreateConstructor<TypedArrayConstructor, 3, JSFunction::FinalizeKind>, GenericCreatePrototype, TypedArrayObject::staticFunctions, TypedArrayObject::protoFunctions, TypedArrayObject::protoAccessors, - nullptr, + FinishTypedArrayInit, ClassSpec::DontDefineConstructor } }; template<typename T> bool ArrayBufferObject::createTypedArrayFromBufferImpl(JSContext *cx, CallArgs args) {
--- a/js/xpconnect/tests/chrome/test_xrayToJS.xul +++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul @@ -174,17 +174,17 @@ https://bugzilla.mozilla.org/show_bug.cg gPrototypeProperties['Array'].push('includes'); } for (var c of typedArrayClasses) { gPrototypeProperties[c] = ["constructor", "BYTES_PER_ELEMENT"]; } gPrototypeProperties['TypedArray'] = ["length", "buffer", "byteLength", "byteOffset", kIteratorSymbol, "subarray", "set", "copyWithin", "find", "findIndex", "indexOf", "lastIndexOf", "reverse", - "join", "every", "some", "reduce", "reduceRight"]; + "join", "every", "some", "reduce", "reduceRight", "entries", "keys", "values"]; if (isNightlyBuild) { gPrototypeProperties['TypedArray'].push('includes'); } for (var c of errorObjectClasses) { gPrototypeProperties[c] = ["constructor", "name", // We don't actually resolve these empty data properties // onto the Xray prototypes, but we list them here to make // the test happy.