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:
parent
029a145fdb
commit
e7b78ac229
@ -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,
|
||||
|
@ -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) \
|
||||
|
@ -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,
|
||||
]);
|
||||
|
||||
});
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user