Implemented Object.keys.
Review URL: http://codereview.chromium.org/201114 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2890 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8a3bce2fa1
commit
77ff957f58
13
LICENSE
13
LICENSE
@ -2,10 +2,15 @@ This license applies to all parts of V8 that are not externally
|
||||
maintained libraries. The externally maintained libraries used by V8
|
||||
are:
|
||||
|
||||
- PCRE test suite, located in test/mjsunit/regexp-pcre.js. This is
|
||||
based on the test suite from PCRE-7.3, which is copyrighted by the
|
||||
University of Cambridge and Google, Inc. The copyright notice and
|
||||
license are embedded in regexp-pcre.js.
|
||||
- PCRE test suite, located in
|
||||
test/mjsunit/third_party/regexp-pcre.js. This is based on the
|
||||
test suite from PCRE-7.3, which is copyrighted by the University
|
||||
of Cambridge and Google, Inc. The copyright notice and license
|
||||
are embedded in regexp-pcre.js.
|
||||
|
||||
- Layout tests, located in test/mjsunit/third_party. These are
|
||||
based on layout tests from webkit.org which are copyrighted by
|
||||
Apple Computer, Inc. and released under a 3-clause BSD license.
|
||||
|
||||
- Dtoa, located under third_party/dtoa. This code is copyrighted by
|
||||
David M. Gay and released under an MIT license.
|
||||
|
@ -1988,7 +1988,8 @@ Local<Array> v8::Object::GetPropertyNames() {
|
||||
ENTER_V8;
|
||||
v8::HandleScope scope;
|
||||
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
|
||||
i::Handle<i::FixedArray> value = i::GetKeysInFixedArrayFor(self);
|
||||
i::Handle<i::FixedArray> value =
|
||||
i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
|
||||
// Because we use caching to speed up enumeration it is important
|
||||
// to never change the result of the basic enumeration function so
|
||||
// we clone the result.
|
||||
|
@ -527,7 +527,8 @@ v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
|
||||
}
|
||||
|
||||
|
||||
Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object) {
|
||||
Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
|
||||
KeyCollectionType type) {
|
||||
Handle<FixedArray> content = Factory::empty_fixed_array();
|
||||
|
||||
JSObject* arguments_boilerplate =
|
||||
@ -575,6 +576,11 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object) {
|
||||
if (!result.IsEmpty())
|
||||
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
|
||||
}
|
||||
|
||||
// If we only want local properties we bail out after the first
|
||||
// iteration.
|
||||
if (type == LOCAL_ONLY)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return content;
|
||||
@ -583,7 +589,8 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object) {
|
||||
|
||||
Handle<JSArray> GetKeysFor(Handle<JSObject> object) {
|
||||
Counters::for_in.Increment();
|
||||
Handle<FixedArray> elements = GetKeysInFixedArrayFor(object);
|
||||
Handle<FixedArray> elements = GetKeysInFixedArrayFor(object,
|
||||
INCLUDE_PROTOS);
|
||||
return Factory::NewJSArrayWithElements(elements);
|
||||
}
|
||||
|
||||
|
@ -265,9 +265,13 @@ v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
|
||||
Handle<JSObject> object);
|
||||
v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
|
||||
Handle<JSObject> object);
|
||||
|
||||
enum KeyCollectionType { LOCAL_ONLY, INCLUDE_PROTOS };
|
||||
|
||||
// Computes the enumerable keys for a JSObject. Used for implementing
|
||||
// "for (n in object) { }".
|
||||
Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object);
|
||||
Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
|
||||
KeyCollectionType type);
|
||||
Handle<JSArray> GetKeysFor(Handle<JSObject> object);
|
||||
Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object);
|
||||
|
||||
|
@ -167,7 +167,8 @@ function FormatMessage(message) {
|
||||
no_input_to_regexp: "No input to %0",
|
||||
result_not_primitive: "Result of %0 must be a primitive, was %1",
|
||||
invalid_json: "String '%0' is not valid JSON",
|
||||
circular_structure: "Converting circular structure to JSON"
|
||||
circular_structure: "Converting circular structure to JSON",
|
||||
object_keys_non_object: "Object.keys called on non-object"
|
||||
};
|
||||
}
|
||||
var format = kMessages[message.type];
|
||||
|
@ -2992,7 +2992,8 @@ static Object* Runtime_GetPropertyNamesFast(Arguments args) {
|
||||
|
||||
HandleScope scope;
|
||||
Handle<JSObject> object(raw_object);
|
||||
Handle<FixedArray> content = GetKeysInFixedArrayFor(object);
|
||||
Handle<FixedArray> content = GetKeysInFixedArrayFor(object,
|
||||
INCLUDE_PROTOS);
|
||||
|
||||
// Test again, since cache may have been built by preceding call.
|
||||
if (object->IsSimpleEnum()) return object->map();
|
||||
@ -3001,6 +3002,22 @@ static Object* Runtime_GetPropertyNamesFast(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_LocalKeys(Arguments args) {
|
||||
ASSERT_EQ(args.length(), 1);
|
||||
CONVERT_CHECKED(JSObject, raw_object, args[0]);
|
||||
HandleScope scope;
|
||||
Handle<JSObject> object(raw_object);
|
||||
Handle<FixedArray> contents = GetKeysInFixedArrayFor(object,
|
||||
LOCAL_ONLY);
|
||||
// Some fast paths through GetKeysInFixedArrayFor reuse a cached
|
||||
// property array and since the result is mutable we have to create
|
||||
// a fresh clone on each invocation.
|
||||
Handle<FixedArray> copy = Factory::NewFixedArray(contents->length());
|
||||
contents->CopyTo(0, *copy, 0, contents->length());
|
||||
return *Factory::NewJSArrayWithElements(copy);
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_GetArgumentsProperty(Arguments args) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 1);
|
||||
@ -5516,7 +5533,7 @@ static Object* Runtime_GetArrayKeys(Arguments args) {
|
||||
if (array->elements()->IsDictionary()) {
|
||||
// Create an array and get all the keys into it, then remove all the
|
||||
// keys that are not integers in the range 0 to length-1.
|
||||
Handle<FixedArray> keys = GetKeysInFixedArrayFor(array);
|
||||
Handle<FixedArray> keys = GetKeysInFixedArrayFor(array, INCLUDE_PROTOS);
|
||||
int keys_length = keys->length();
|
||||
for (int i = 0; i < keys_length; i++) {
|
||||
Object* key = keys->get(i);
|
||||
@ -6271,7 +6288,7 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
|
||||
if (function_context->has_extension() &&
|
||||
!function_context->IsGlobalContext()) {
|
||||
Handle<JSObject> ext(JSObject::cast(function_context->extension()));
|
||||
Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
|
||||
Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
|
||||
for (int i = 0; i < keys->length(); i++) {
|
||||
// Names of variables introduced by eval are strings.
|
||||
ASSERT(keys->get(i)->IsString());
|
||||
@ -6320,7 +6337,7 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
|
||||
// be variables introduced by eval.
|
||||
if (context->has_extension()) {
|
||||
Handle<JSObject> ext(JSObject::cast(context->extension()));
|
||||
Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
|
||||
Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
|
||||
for (int i = 0; i < keys->length(); i++) {
|
||||
// Names of variables introduced by eval are strings.
|
||||
ASSERT(keys->get(i)->IsString());
|
||||
|
@ -258,6 +258,8 @@ namespace internal {
|
||||
F(Abort, 2, 1) \
|
||||
/* Logging */ \
|
||||
F(Log, 2, 1) \
|
||||
/* ES5 */ \
|
||||
F(LocalKeys, 1, 1) \
|
||||
\
|
||||
/* Pseudo functions - handled as macros by parser */ \
|
||||
F(IS_VAR, 1, 1)
|
||||
|
@ -276,6 +276,13 @@ function ObjectLookupSetter(name) {
|
||||
}
|
||||
|
||||
|
||||
function ObjectKeys(obj) {
|
||||
if (!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj))
|
||||
throw MakeTypeError('object_keys_non_object', [obj]);
|
||||
return %LocalKeys(obj);
|
||||
}
|
||||
|
||||
|
||||
%SetCode($Object, function(x) {
|
||||
if (%_IsConstructCall()) {
|
||||
if (x == null) return this;
|
||||
@ -304,6 +311,9 @@ function SetupObject() {
|
||||
"__defineSetter__", ObjectDefineSetter,
|
||||
"__lookupSetter__", ObjectLookupSetter
|
||||
));
|
||||
InstallFunctions($Object, DONT_ENUM, $Array(
|
||||
"keys", ObjectKeys
|
||||
));
|
||||
}
|
||||
|
||||
SetupObject();
|
||||
|
@ -112,8 +112,9 @@ class MjsunitTestConfiguration(test.TestConfiguration):
|
||||
mjsunit = [current_path + [t] for t in self.Ls(self.root)]
|
||||
regress = [current_path + ['regress', t] for t in self.Ls(join(self.root, 'regress'))]
|
||||
bugs = [current_path + ['bugs', t] for t in self.Ls(join(self.root, 'bugs'))]
|
||||
third_party = [current_path + ['third_party', t] for t in self.Ls(join(self.root, 'third_party'))]
|
||||
tools = [current_path + ['tools', t] for t in self.Ls(join(self.root, 'tools'))]
|
||||
all_tests = mjsunit + regress + bugs + tools
|
||||
all_tests = mjsunit + regress + bugs + third_party + tools
|
||||
result = []
|
||||
for test in all_tests:
|
||||
if self.Contains(path, test):
|
||||
|
@ -1,29 +1,33 @@
|
||||
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder(s) nor the names of any
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Simple splice tests based on webkit layout tests.
|
||||
var arr = ['a','b','c','d'];
|
||||
@ -56,5 +60,3 @@ assertArrayEquals([], arr.splice(2, 0))
|
||||
assertArrayEquals(['a','b','c'], arr);
|
||||
assertArrayEquals(['c'], arr.splice(2, 100))
|
||||
assertArrayEquals(['a','b'], arr);
|
||||
|
||||
|
65
test/mjsunit/third_party/object-keys.js
vendored
Normal file
65
test/mjsunit/third_party/object-keys.js
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder(s) nor the names of any
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Based on LayoutTests/fast/js/Object-keys.html
|
||||
|
||||
assertThrows(function () { Object.keys(2) }, TypeError);
|
||||
assertThrows(function () { Object.keys("foo") }, TypeError);
|
||||
assertThrows(function () { Object.keys(null) }, TypeError);
|
||||
assertThrows(function () { Object.keys(undefined) }, TypeError);
|
||||
|
||||
assertEquals(Object.keys({}), []);
|
||||
assertEquals(Object.keys({a:null}), ['a']);
|
||||
assertEquals(Object.keys({a:null, b:null}), ['a', 'b']);
|
||||
assertEquals(Object.keys({b:null, a:null}), ['b', 'a']);
|
||||
assertEquals(Object.keys([]), []);
|
||||
assertEquals(Object.keys([null]), ['0']);
|
||||
assertEquals(Object.keys([null,null]), ['0', '1']);
|
||||
assertEquals(Object.keys([null,null,,,,null]), ['0', '1', '5']);
|
||||
assertEquals(Object.keys({__proto__:{a:null}}), []);
|
||||
assertEquals(Object.keys({__proto__:[1,2,3]}), []);
|
||||
var x = [];
|
||||
x.__proto__ = [1, 2, 3];
|
||||
assertEquals(Object.keys(x), []);
|
||||
|
||||
function argsTest(a, b, c) {
|
||||
assertEquals([], Object.keys(arguments));
|
||||
}
|
||||
|
||||
argsTest(1, 2, 3);
|
||||
|
||||
var literal = {a: 1, b: 2, c: 3};
|
||||
var keysBefore = Object.keys(literal);
|
||||
assertEquals(['a', 'b', 'c'], keysBefore);
|
||||
keysBefore[0] = 'x';
|
||||
var keysAfter = Object.keys(literal);
|
||||
assertEquals(['a', 'b', 'c'], keysAfter);
|
||||
assertEquals(['x', 'b', 'c'], keysBefore);
|
Loading…
Reference in New Issue
Block a user