Expose more %ArrayPrototype% functions to the public API.

In addition to Array.prototype.values() which is already exposed, Blink
needs access to entries(), forEach() and keys() to properly set the
corresponding functions in value iterators for WebIDL conformance.

Add a few new entries to NATIVE_CONTEXT_IMPORTED_FIELDS and expand
V8_INTRINSICS_LIST, as well as some API tests for all these new exposed
functions.

BUG=chromium:632935
R=caitp@igalia.com,jochen@chromium.org,verwaest@chromium.org,yukishiino@chromium.org

Review-Url: https://codereview.chromium.org/2670833008
Cr-Commit-Position: refs/heads/master@{#43017}
This commit is contained in:
raphael.kubo.da.costa 2017-02-07 13:42:06 -08:00 committed by Commit bot
parent 029a145fdb
commit e7b78ac229
4 changed files with 84 additions and 11 deletions

View File

@ -4618,8 +4618,11 @@ class V8_EXPORT External : public Value {
static void CheckCast(v8::Value* obj);
};
#define V8_INTRINSICS_LIST(F) F(ArrayProto_values, array_values_iterator)
#define V8_INTRINSICS_LIST(F) \
F(ArrayProto_entries, array_entries_iterator) \
F(ArrayProto_forEach, array_for_each_iterator) \
F(ArrayProto_keys, array_keys_iterator) \
F(ArrayProto_values, array_values_iterator)
enum Intrinsic {
#define V8_DECL_INTRINSIC(name, iname) k##name,

View File

@ -80,6 +80,9 @@ enum ContextLookupFlags {
V(ARRAY_SPLICE_INDEX, JSFunction, array_splice) \
V(ARRAY_SLICE_INDEX, JSFunction, array_slice) \
V(ARRAY_UNSHIFT_INDEX, JSFunction, array_unshift) \
V(ARRAY_ENTRIES_ITERATOR_INDEX, JSFunction, array_entries_iterator) \
V(ARRAY_FOR_EACH_ITERATOR_INDEX, JSFunction, array_for_each_iterator) \
V(ARRAY_KEYS_ITERATOR_INDEX, JSFunction, array_keys_iterator) \
V(ARRAY_VALUES_ITERATOR_INDEX, JSFunction, array_values_iterator) \
V(ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX, JSFunction, \
async_function_await_caught) \

View File

@ -1527,7 +1527,14 @@ function getFunction(name, jsBuiltin, len) {
return f;
};
var ArrayValues = getFunction("values", null, 0);
// Array prototype functions that return iterators. They are exposed to the
// public API via Template::SetIntrinsicDataProperty().
var IteratorFunctions = {
"entries": getFunction("entries", null, 0),
"forEach": getFunction("forEach", ArrayForEach, 1),
"keys": getFunction("keys", null, 0),
"values": getFunction("values", null, 0)
}
// Set up non-enumerable functions of the Array.prototype object and
// set their names.
@ -1546,7 +1553,6 @@ utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
"splice", getFunction("splice", ArraySplice, 2),
"sort", getFunction("sort", ArraySort),
"filter", getFunction("filter", ArrayFilter, 1),
"forEach", getFunction("forEach", ArrayForEach, 1),
"some", getFunction("some", ArraySome, 1),
"every", getFunction("every", ArrayEvery, 1),
"map", getFunction("map", ArrayMap, 1),
@ -1559,14 +1565,18 @@ utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
"findIndex", getFunction("findIndex", ArrayFindIndex, 1),
"fill", getFunction("fill", ArrayFill, 1),
"includes", getFunction("includes", null, 1),
"keys", getFunction("keys", null, 0),
"entries", getFunction("entries", null, 0),
iteratorSymbol, ArrayValues
"entries", IteratorFunctions.entries,
"forEach", IteratorFunctions.forEach,
"keys", IteratorFunctions.keys,
iteratorSymbol, IteratorFunctions.values
]);
utils.ForEachFunction = GlobalArray.prototype.forEach;
%FunctionSetName(ArrayValues, "values");
%FunctionSetName(IteratorFunctions.entries, "entries");
%FunctionSetName(IteratorFunctions.forEach, "forEach");
%FunctionSetName(IteratorFunctions.keys, "keys");
%FunctionSetName(IteratorFunctions.values, "values");
%FinishArrayPrototypeSetup(GlobalArray.prototype);
@ -1609,7 +1619,7 @@ utils.Export(function(to) {
to.ArrayJoin = ArrayJoin;
to.ArrayPush = ArrayPush;
to.ArrayToString = ArrayToString;
to.ArrayValues = ArrayValues;
to.ArrayValues = IteratorFunctions.values,
to.InnerArrayEvery = InnerArrayEvery;
to.InnerArrayFill = InnerArrayFill;
to.InnerArrayFilter = InnerArrayFilter;
@ -1627,13 +1637,16 @@ utils.Export(function(to) {
});
%InstallToContext([
"array_entries_iterator", IteratorFunctions.entries,
"array_for_each_iterator", IteratorFunctions.forEach,
"array_keys_iterator", IteratorFunctions.keys,
"array_pop", ArrayPop,
"array_push", ArrayPush,
"array_shift", ArrayShift,
"array_splice", ArraySplice,
"array_slice", ArraySlice,
"array_unshift", ArrayUnshift,
"array_values_iterator", ArrayValues,
"array_values_iterator", IteratorFunctions.values,
]);
});

View File

@ -25899,8 +25899,62 @@ TEST(AccessCheckedToStringTag) {
CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
}
TEST(ObjectTemplateArrayProtoIntrinsics) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
LocalContext env;
TEST(ObjectTemplateIntrinsics) {
Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
object_template->SetIntrinsicDataProperty(v8_str("prop_entries"),
v8::kArrayProto_entries);
object_template->SetIntrinsicDataProperty(v8_str("prop_forEach"),
v8::kArrayProto_forEach);
object_template->SetIntrinsicDataProperty(v8_str("prop_keys"),
v8::kArrayProto_keys);
object_template->SetIntrinsicDataProperty(v8_str("prop_values"),
v8::kArrayProto_values);
Local<Object> object =
object_template->NewInstance(env.local()).ToLocalChecked();
CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
const struct {
const char* const object_property_name;
const char* const array_property_name;
} intrinsics_comparisons[] = {
{"prop_entries", "Array.prototype.entries"},
{"prop_forEach", "Array.prototype.forEach"},
{"prop_keys", "Array.prototype.keys"},
{"prop_values", "Array.prototype[Symbol.iterator]"},
};
for (unsigned i = 0; i < arraysize(intrinsics_comparisons); i++) {
i::ScopedVector<char> test_string(64);
i::SNPrintF(test_string, "typeof obj1.%s",
intrinsics_comparisons[i].object_property_name);
ExpectString(test_string.start(), "function");
i::SNPrintF(test_string, "obj1.%s === %s",
intrinsics_comparisons[i].object_property_name,
intrinsics_comparisons[i].array_property_name);
ExpectTrue(test_string.start());
i::SNPrintF(test_string, "obj1.%s = 42",
intrinsics_comparisons[i].object_property_name);
CompileRun(test_string.start());
i::SNPrintF(test_string, "obj1.%s === %s",
intrinsics_comparisons[i].object_property_name,
intrinsics_comparisons[i].array_property_name);
ExpectFalse(test_string.start());
i::SNPrintF(test_string, "typeof obj1.%s",
intrinsics_comparisons[i].object_property_name);
ExpectString(test_string.start(), "number");
}
}
TEST(ObjectTemplatePerContextIntrinsics) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
LocalContext env;