Implement ES6 Array.of()
BUG=v8:3427 LOG=N R=rossberg@chromium.org Review URL: https://codereview.chromium.org/364853009 Patch from Diego Pino <dpino@igalia.com>. git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23194 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
85058ce97d
commit
30af557955
@ -123,11 +123,29 @@ function ArrayFill(value /* [, start [, end ] ] */) { // length == 1
|
||||
return array;
|
||||
}
|
||||
|
||||
// ES6, draft 05-22-14, section 22.1.2.3
|
||||
function ArrayOf() {
|
||||
var length = %_ArgumentsLength();
|
||||
var constructor = this;
|
||||
// TODO: Implement IsConstructor (ES6 section 7.2.5)
|
||||
var array = IS_SPEC_FUNCTION(constructor) ? new constructor(length) : [];
|
||||
for (var i = 0; i < length; i++) {
|
||||
%AddElement(array, i, %_Arguments(i), NONE);
|
||||
}
|
||||
array.length = length;
|
||||
return array;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function HarmonyArrayExtendArrayPrototype() {
|
||||
%CheckIsBootstrapping();
|
||||
|
||||
// Set up non-enumerable functions on the Array object.
|
||||
InstallFunctions($Array, DONT_ENUM, $Array(
|
||||
"of", ArrayOf
|
||||
));
|
||||
|
||||
// Set up the non-enumerable functions on the Array prototype object.
|
||||
InstallFunctions($Array.prototype, DONT_ENUM, $Array(
|
||||
"find", ArrayFind,
|
||||
|
@ -5354,6 +5354,33 @@ RUNTIME_FUNCTION(Runtime_SetProperty) {
|
||||
}
|
||||
|
||||
|
||||
// Adds an element to an array.
|
||||
// This is used to create an indexed data property into an array.
|
||||
RUNTIME_FUNCTION(Runtime_AddElement) {
|
||||
HandleScope scope(isolate);
|
||||
RUNTIME_ASSERT(args.length() == 4);
|
||||
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
|
||||
CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
|
||||
RUNTIME_ASSERT(
|
||||
(unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
|
||||
// Compute attributes.
|
||||
PropertyAttributes attributes =
|
||||
static_cast<PropertyAttributes>(unchecked_attributes);
|
||||
|
||||
uint32_t index = 0;
|
||||
key->ToArrayIndex(&index);
|
||||
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result, JSObject::SetElement(object, index, value, attributes,
|
||||
SLOPPY, false, DEFINE_PROPERTY));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
|
||||
HandleScope scope(isolate);
|
||||
RUNTIME_ASSERT(args.length() == 2);
|
||||
|
@ -233,6 +233,7 @@ namespace internal {
|
||||
F(AddNamedProperty, 4, 1) \
|
||||
F(AddPropertyForTemplate, 4, 1) \
|
||||
F(SetProperty, 4, 1) \
|
||||
F(AddElement, 4, 1) \
|
||||
F(DefineApiAccessorProperty, 5, 1) \
|
||||
F(DefineDataPropertyUnchecked, 4, 1) \
|
||||
F(DefineAccessorPropertyUnchecked, 5, 1) \
|
||||
|
164
test/mjsunit/harmony/array-of.js
Normal file
164
test/mjsunit/harmony/array-of.js
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Based on Mozilla Array.of() tests at http://dxr.mozilla.org/mozilla-central/source/js/src/jit-test/tests/collections
|
||||
|
||||
// Flags: --harmony-arrays
|
||||
|
||||
|
||||
|
||||
// Array.of makes real arrays.
|
||||
|
||||
function check(a) {
|
||||
assertEquals(Object.getPrototypeOf(a), Array.prototype);
|
||||
assertEquals(Array.isArray(a), true);
|
||||
a[9] = 9;
|
||||
assertEquals(a.length, 10);
|
||||
}
|
||||
|
||||
|
||||
check(Array.of());
|
||||
check(Array.of(0));
|
||||
check(Array.of(0, 1, 2));
|
||||
var f = Array.of;
|
||||
check(f());
|
||||
|
||||
|
||||
// Array.of basics
|
||||
|
||||
var a = Array.of();
|
||||
|
||||
assertEquals(a.length, 0);
|
||||
a = Array.of(undefined, null, 3.14, []);
|
||||
assertEquals(a, [undefined, null, 3.14, []]);
|
||||
a = [];
|
||||
for (var i = 0; i < 1000; i++)
|
||||
a[i] = i;
|
||||
assertEquals(Array.of.apply(null, a), a);
|
||||
|
||||
|
||||
// Array.of does not leave holes
|
||||
|
||||
assertEquals(Array.of(undefined), [undefined]);
|
||||
assertEquals(Array.of(undefined, undefined), [undefined, undefined]);
|
||||
assertEquals(Array.of.apply(null, [,,undefined]), [undefined, undefined, undefined]);
|
||||
assertEquals(Array.of.apply(null, Array(4)), [undefined, undefined, undefined, undefined]);
|
||||
|
||||
|
||||
// Array.of can be transplanted to other classes.
|
||||
|
||||
var hits = 0;
|
||||
function Bag() {
|
||||
hits++;
|
||||
}
|
||||
Bag.of = Array.of;
|
||||
|
||||
hits = 0;
|
||||
var actual = Bag.of("zero", "one");
|
||||
assertEquals(hits, 1);
|
||||
|
||||
hits = 0;
|
||||
var expected = new Bag;
|
||||
expected[0] = "zero";
|
||||
expected[1] = "one";
|
||||
expected.length = 2;
|
||||
assertEquals(areSame(actual, expected), true);
|
||||
|
||||
hits = 0;
|
||||
actual = Array.of.call(Bag, "zero", "one");
|
||||
assertEquals(hits, 1);
|
||||
assertEquals(areSame(actual, expected), true);
|
||||
|
||||
function areSame(object, array) {
|
||||
var result = object.length == array.length;
|
||||
for (var i = 0; i < object.length; i++) {
|
||||
result = result && object[i] == array[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Array.of does not trigger prototype setters.
|
||||
// (It defines elements rather than assigning to them.)
|
||||
|
||||
var status = "pass";
|
||||
Object.defineProperty(Array.prototype, "0", {set: function(v) {status = "FAIL 1"}});
|
||||
assertEquals(Array.of(1)[0], 1);
|
||||
assertEquals(status, "pass");
|
||||
|
||||
Object.defineProperty(Bag.prototype, "0", {set: function(v) {status = "FAIL 2"}});
|
||||
assertEquals(Bag.of(1)[0], 1);
|
||||
assertEquals(status, "pass");
|
||||
|
||||
|
||||
// Array.of passes the number of arguments to the constructor it calls.
|
||||
|
||||
var hits = 0;
|
||||
|
||||
function Herd(n) {
|
||||
assertEquals(arguments.length, 1);
|
||||
assertEquals(n, 5);
|
||||
hits++;
|
||||
}
|
||||
|
||||
Herd.of = Array.of;
|
||||
Herd.of("sheep", "cattle", "elephants", "whales", "seals");
|
||||
assertEquals(hits, 1);
|
||||
|
||||
|
||||
// Array.of calls a "length" setter if one is present.
|
||||
|
||||
var hits = 0;
|
||||
var lastObj = null, lastVal = undefined;
|
||||
function setter(v) {
|
||||
hits++;
|
||||
lastObj = this;
|
||||
lastVal = v;
|
||||
}
|
||||
|
||||
// when the setter is on the new object
|
||||
function Pack() {
|
||||
Object.defineProperty(this, "length", {set: setter});
|
||||
}
|
||||
Pack.of = Array.of;
|
||||
var pack = Pack.of("wolves", "cards", "cigarettes", "lies");
|
||||
assertEquals(lastObj, pack);
|
||||
assertEquals(lastVal, 4);
|
||||
|
||||
// when the setter is on the new object's prototype
|
||||
function Bevy() {}
|
||||
Object.defineProperty(Bevy.prototype, "length", {set: setter});
|
||||
Bevy.of = Array.of;
|
||||
var bevy = Bevy.of("quail");
|
||||
assertEquals(lastObj, bevy);
|
||||
assertEquals(lastVal, 1);
|
||||
|
||||
|
||||
// Array.of does a strict assignment to the new object's .length.
|
||||
// The assignment is strict even if the code we're calling from is not strict.
|
||||
|
||||
function Empty() {}
|
||||
Empty.of = Array.of;
|
||||
Object.defineProperty(Empty.prototype, "length", {get: function() { return 0; }});
|
||||
|
||||
var nothing = new Empty;
|
||||
nothing.length = 2; // no exception; this is not a strict mode assignment
|
||||
|
||||
assertThrows(function() { Empty.of(); }, TypeError);
|
||||
|
||||
|
||||
// Check superficial features of Array.of.
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(Array, "of");
|
||||
|
||||
assertEquals(desc.configurable, true);
|
||||
assertEquals(desc.enumerable, false);
|
||||
assertEquals(desc.writable, true);
|
||||
assertEquals(Array.of.length, 0);
|
||||
assertThrows(function() { new Array.of() }, TypeError); // not a constructor
|
||||
|
||||
// When the this-value passed in is not a constructor, the result is an array.
|
||||
[undefined, null, false, "cow"].forEach(function(val) {
|
||||
assertEquals(Array.isArray(Array.of(val)), true);
|
||||
});
|
@ -47,11 +47,11 @@ EXPAND_MACROS = [
|
||||
# that the parser doesn't bit-rot. Change the values as needed when you add,
|
||||
# remove or change runtime functions, but make sure we don't lose our ability
|
||||
# to parse them!
|
||||
EXPECTED_FUNCTION_COUNT = 428
|
||||
EXPECTED_FUNCTION_COUNT = 429
|
||||
EXPECTED_FUZZABLE_COUNT = 331
|
||||
EXPECTED_CCTEST_COUNT = 7
|
||||
EXPECTED_UNKNOWN_COUNT = 16
|
||||
EXPECTED_BUILTINS_COUNT = 808
|
||||
EXPECTED_UNKNOWN_COUNT = 17
|
||||
EXPECTED_BUILTINS_COUNT = 809
|
||||
|
||||
|
||||
# Don't call these at all.
|
||||
|
Loading…
Reference in New Issue
Block a user