deps: backport c608122b from upstream
Original commit message: [api][keys] Allow skipping indices for Proxies with GetPropertyNames Bug: v8:7942 Change-Id: I7b3740b04cbcaa56dc809150900ab8d821b054ce Reviewed-on: https://chromium-review.googlesource.com/1156544 Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#54821} PR-URL: https://github.com/nodejs/node/pull/22210 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Gus Caplan <me@gus.host>
This commit is contained in:
parent
5442c28b65
commit
c4007f0096
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
# Reset this number to 0 on major V8 upgrades.
|
# Reset this number to 0 on major V8 upgrades.
|
||||||
# Increment by one for each non-official patch applied to deps/v8.
|
# Increment by one for each non-official patch applied to deps/v8.
|
||||||
'v8_embedder_string': '-node.13',
|
'v8_embedder_string': '-node.14',
|
||||||
|
|
||||||
# Enable disassembler for `--print-code` v8 options
|
# Enable disassembler for `--print-code` v8 options
|
||||||
'v8_enable_disassembler': 1,
|
'v8_enable_disassembler': 1,
|
||||||
|
46
deps/v8/src/keys.cc
vendored
46
deps/v8/src/keys.cc
vendored
@ -37,10 +37,10 @@ static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
|
|||||||
// static
|
// static
|
||||||
MaybeHandle<FixedArray> KeyAccumulator::GetKeys(
|
MaybeHandle<FixedArray> KeyAccumulator::GetKeys(
|
||||||
Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
|
Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
|
||||||
GetKeysConversion keys_conversion, bool is_for_in) {
|
GetKeysConversion keys_conversion, bool is_for_in, bool skip_indices) {
|
||||||
Isolate* isolate = object->GetIsolate();
|
Isolate* isolate = object->GetIsolate();
|
||||||
FastKeyAccumulator accumulator(isolate, object, mode, filter);
|
FastKeyAccumulator accumulator(isolate, object, mode, filter, is_for_in,
|
||||||
accumulator.set_is_for_in(is_for_in);
|
skip_indices);
|
||||||
return accumulator.GetKeys(keys_conversion);
|
return accumulator.GetKeys(keys_conversion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +356,8 @@ Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
|
|||||||
template <bool fast_properties>
|
template <bool fast_properties>
|
||||||
MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
|
MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
GetKeysConversion convert) {
|
GetKeysConversion convert,
|
||||||
|
bool skip_indices) {
|
||||||
Handle<FixedArray> keys;
|
Handle<FixedArray> keys;
|
||||||
ElementsAccessor* accessor = object->GetElementsAccessor();
|
ElementsAccessor* accessor = object->GetElementsAccessor();
|
||||||
if (fast_properties) {
|
if (fast_properties) {
|
||||||
@ -365,8 +366,13 @@ MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
|
|||||||
// TODO(cbruni): preallocate big enough array to also hold elements.
|
// TODO(cbruni): preallocate big enough array to also hold elements.
|
||||||
keys = KeyAccumulator::GetOwnEnumPropertyKeys(isolate, object);
|
keys = KeyAccumulator::GetOwnEnumPropertyKeys(isolate, object);
|
||||||
}
|
}
|
||||||
MaybeHandle<FixedArray> result =
|
MaybeHandle<FixedArray> result;
|
||||||
accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE);
|
if (skip_indices) {
|
||||||
|
result = keys;
|
||||||
|
} else {
|
||||||
|
result =
|
||||||
|
accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE);
|
||||||
|
}
|
||||||
|
|
||||||
if (FLAG_trace_for_in_enumerate) {
|
if (FLAG_trace_for_in_enumerate) {
|
||||||
PrintF("| strings=%d symbols=0 elements=%u || prototypes>=1 ||\n",
|
PrintF("| strings=%d symbols=0 elements=%u || prototypes>=1 ||\n",
|
||||||
@ -404,7 +410,8 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
|
|||||||
|
|
||||||
// Do not try to use the enum-cache for dict-mode objects.
|
// Do not try to use the enum-cache for dict-mode objects.
|
||||||
if (map->is_dictionary_map()) {
|
if (map->is_dictionary_map()) {
|
||||||
return GetOwnKeysWithElements<false>(isolate_, object, keys_conversion);
|
return GetOwnKeysWithElements<false>(isolate_, object, keys_conversion,
|
||||||
|
skip_indices_);
|
||||||
}
|
}
|
||||||
int enum_length = receiver_->map()->EnumLength();
|
int enum_length = receiver_->map()->EnumLength();
|
||||||
if (enum_length == kInvalidEnumCacheSentinel) {
|
if (enum_length == kInvalidEnumCacheSentinel) {
|
||||||
@ -422,7 +429,8 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
|
|||||||
}
|
}
|
||||||
// The properties-only case failed because there were probably elements on the
|
// The properties-only case failed because there were probably elements on the
|
||||||
// receiver.
|
// receiver.
|
||||||
return GetOwnKeysWithElements<true>(isolate_, object, keys_conversion);
|
return GetOwnKeysWithElements<true>(isolate_, object, keys_conversion,
|
||||||
|
skip_indices_);
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeHandle<FixedArray>
|
MaybeHandle<FixedArray>
|
||||||
@ -451,6 +459,7 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow(
|
|||||||
GetKeysConversion keys_conversion) {
|
GetKeysConversion keys_conversion) {
|
||||||
KeyAccumulator accumulator(isolate_, mode_, filter_);
|
KeyAccumulator accumulator(isolate_, mode_, filter_);
|
||||||
accumulator.set_is_for_in(is_for_in_);
|
accumulator.set_is_for_in(is_for_in_);
|
||||||
|
accumulator.set_skip_indices(skip_indices_);
|
||||||
accumulator.set_last_non_empty_prototype(last_non_empty_prototype_);
|
accumulator.set_last_non_empty_prototype(last_non_empty_prototype_);
|
||||||
|
|
||||||
MAYBE_RETURN(accumulator.CollectKeys(receiver_, receiver_),
|
MAYBE_RETURN(accumulator.CollectKeys(receiver_, receiver_),
|
||||||
@ -698,13 +707,15 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
|
|||||||
Maybe<bool> KeyAccumulator::CollectAccessCheckInterceptorKeys(
|
Maybe<bool> KeyAccumulator::CollectAccessCheckInterceptorKeys(
|
||||||
Handle<AccessCheckInfo> access_check_info, Handle<JSReceiver> receiver,
|
Handle<AccessCheckInfo> access_check_info, Handle<JSReceiver> receiver,
|
||||||
Handle<JSObject> object) {
|
Handle<JSObject> object) {
|
||||||
MAYBE_RETURN((CollectInterceptorKeysInternal(
|
if (!skip_indices_) {
|
||||||
receiver, object,
|
MAYBE_RETURN((CollectInterceptorKeysInternal(
|
||||||
handle(InterceptorInfo::cast(
|
receiver, object,
|
||||||
access_check_info->indexed_interceptor()),
|
handle(InterceptorInfo::cast(
|
||||||
isolate_),
|
access_check_info->indexed_interceptor()),
|
||||||
this, kIndexed)),
|
isolate_),
|
||||||
Nothing<bool>());
|
this, kIndexed)),
|
||||||
|
Nothing<bool>());
|
||||||
|
}
|
||||||
MAYBE_RETURN(
|
MAYBE_RETURN(
|
||||||
(CollectInterceptorKeysInternal(
|
(CollectInterceptorKeysInternal(
|
||||||
receiver, object,
|
receiver, object,
|
||||||
@ -935,8 +946,9 @@ Maybe<bool> KeyAccumulator::CollectOwnJSProxyTargetKeys(
|
|||||||
Handle<FixedArray> keys;
|
Handle<FixedArray> keys;
|
||||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||||
isolate_, keys,
|
isolate_, keys,
|
||||||
KeyAccumulator::GetKeys(target, KeyCollectionMode::kOwnOnly, filter_,
|
KeyAccumulator::GetKeys(
|
||||||
GetKeysConversion::kConvertToString, is_for_in_),
|
target, KeyCollectionMode::kOwnOnly, filter_,
|
||||||
|
GetKeysConversion::kConvertToString, is_for_in_, skip_indices_),
|
||||||
Nothing<bool>());
|
Nothing<bool>());
|
||||||
Maybe<bool> result = AddKeysFromJSProxy(proxy, keys);
|
Maybe<bool> result = AddKeysFromJSProxy(proxy, keys);
|
||||||
return result;
|
return result;
|
||||||
|
14
deps/v8/src/keys.h
vendored
14
deps/v8/src/keys.h
vendored
@ -40,7 +40,7 @@ class KeyAccumulator final BASE_EMBEDDED {
|
|||||||
static MaybeHandle<FixedArray> GetKeys(
|
static MaybeHandle<FixedArray> GetKeys(
|
||||||
Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
|
Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
|
||||||
GetKeysConversion keys_conversion = GetKeysConversion::kKeepNumbers,
|
GetKeysConversion keys_conversion = GetKeysConversion::kKeepNumbers,
|
||||||
bool is_for_in = false);
|
bool is_for_in = false, bool skip_indices = false);
|
||||||
|
|
||||||
Handle<FixedArray> GetKeys(
|
Handle<FixedArray> GetKeys(
|
||||||
GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
|
GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
|
||||||
@ -128,14 +128,19 @@ class KeyAccumulator final BASE_EMBEDDED {
|
|||||||
class FastKeyAccumulator {
|
class FastKeyAccumulator {
|
||||||
public:
|
public:
|
||||||
FastKeyAccumulator(Isolate* isolate, Handle<JSReceiver> receiver,
|
FastKeyAccumulator(Isolate* isolate, Handle<JSReceiver> receiver,
|
||||||
KeyCollectionMode mode, PropertyFilter filter)
|
KeyCollectionMode mode, PropertyFilter filter,
|
||||||
: isolate_(isolate), receiver_(receiver), mode_(mode), filter_(filter) {
|
bool is_for_in = false, bool skip_indices = false)
|
||||||
|
: isolate_(isolate),
|
||||||
|
receiver_(receiver),
|
||||||
|
mode_(mode),
|
||||||
|
filter_(filter),
|
||||||
|
is_for_in_(is_for_in),
|
||||||
|
skip_indices_(skip_indices) {
|
||||||
Prepare();
|
Prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_receiver_simple_enum() { return is_receiver_simple_enum_; }
|
bool is_receiver_simple_enum() { return is_receiver_simple_enum_; }
|
||||||
bool has_empty_prototype() { return has_empty_prototype_; }
|
bool has_empty_prototype() { return has_empty_prototype_; }
|
||||||
void set_is_for_in(bool value) { is_for_in_ = value; }
|
|
||||||
|
|
||||||
MaybeHandle<FixedArray> GetKeys(
|
MaybeHandle<FixedArray> GetKeys(
|
||||||
GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
|
GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
|
||||||
@ -153,6 +158,7 @@ class FastKeyAccumulator {
|
|||||||
KeyCollectionMode mode_;
|
KeyCollectionMode mode_;
|
||||||
PropertyFilter filter_;
|
PropertyFilter filter_;
|
||||||
bool is_for_in_ = false;
|
bool is_for_in_ = false;
|
||||||
|
bool skip_indices_ = false;
|
||||||
bool is_receiver_simple_enum_ = false;
|
bool is_receiver_simple_enum_ = false;
|
||||||
bool has_empty_prototype_ = false;
|
bool has_empty_prototype_ = false;
|
||||||
|
|
||||||
|
3
deps/v8/src/runtime/runtime-forin.cc
vendored
3
deps/v8/src/runtime/runtime-forin.cc
vendored
@ -25,8 +25,7 @@ MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) {
|
|||||||
JSObject::MakePrototypesFast(receiver, kStartAtReceiver, isolate);
|
JSObject::MakePrototypesFast(receiver, kStartAtReceiver, isolate);
|
||||||
FastKeyAccumulator accumulator(isolate, receiver,
|
FastKeyAccumulator accumulator(isolate, receiver,
|
||||||
KeyCollectionMode::kIncludePrototypes,
|
KeyCollectionMode::kIncludePrototypes,
|
||||||
ENUMERABLE_STRINGS);
|
ENUMERABLE_STRINGS, true);
|
||||||
accumulator.set_is_for_in(true);
|
|
||||||
// Test if we have an enum cache for {receiver}.
|
// Test if we have an enum cache for {receiver}.
|
||||||
if (!accumulator.is_receiver_simple_enum()) {
|
if (!accumulator.is_receiver_simple_enum()) {
|
||||||
Handle<FixedArray> keys;
|
Handle<FixedArray> keys;
|
||||||
|
97
deps/v8/test/cctest/test-api.cc
vendored
97
deps/v8/test/cctest/test-api.cc
vendored
@ -15356,14 +15356,107 @@ THREADED_TEST(PropertyEnumeration2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
THREADED_TEST(PropertyNames) {
|
THREADED_TEST(GetPropertyNames) {
|
||||||
LocalContext context;
|
LocalContext context;
|
||||||
v8::Isolate* isolate = context->GetIsolate();
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
v8::Local<v8::Value> result = CompileRun(
|
v8::Local<v8::Value> result = CompileRun(
|
||||||
"var result = {0: 0, 1: 1, a: 2, b: 3};"
|
"var result = {0: 0, 1: 1, a: 2, b: 3};"
|
||||||
"result[Symbol('symbol')] = true;"
|
"result[Symbol('symbol')] = true;"
|
||||||
"result.__proto__ = {2: 4, 3: 5, c: 6, d: 7};"
|
"result.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
|
||||||
|
"result;");
|
||||||
|
v8::Local<v8::Object> object = result.As<v8::Object>();
|
||||||
|
v8::PropertyFilter default_filter =
|
||||||
|
static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
|
||||||
|
v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
|
||||||
|
|
||||||
|
v8::Local<v8::Array> properties =
|
||||||
|
object->GetPropertyNames(context.local()).ToLocalChecked();
|
||||||
|
const char* expected_properties1[] = {"0", "1", "a", "b", "2", "3", "c", "d"};
|
||||||
|
CheckStringArray(isolate, properties, 8, expected_properties1);
|
||||||
|
|
||||||
|
properties =
|
||||||
|
object
|
||||||
|
->GetPropertyNames(context.local(),
|
||||||
|
v8::KeyCollectionMode::kIncludePrototypes,
|
||||||
|
default_filter, v8::IndexFilter::kIncludeIndices)
|
||||||
|
.ToLocalChecked();
|
||||||
|
CheckStringArray(isolate, properties, 8, expected_properties1);
|
||||||
|
|
||||||
|
properties = object
|
||||||
|
->GetPropertyNames(context.local(),
|
||||||
|
v8::KeyCollectionMode::kIncludePrototypes,
|
||||||
|
include_symbols_filter,
|
||||||
|
v8::IndexFilter::kIncludeIndices)
|
||||||
|
.ToLocalChecked();
|
||||||
|
const char* expected_properties1_1[] = {"0", "1", "a", "b", nullptr,
|
||||||
|
"2", "3", "c", "d"};
|
||||||
|
CheckStringArray(isolate, properties, 9, expected_properties1_1);
|
||||||
|
CheckIsSymbolAt(isolate, properties, 4, "symbol");
|
||||||
|
|
||||||
|
properties =
|
||||||
|
object
|
||||||
|
->GetPropertyNames(context.local(),
|
||||||
|
v8::KeyCollectionMode::kIncludePrototypes,
|
||||||
|
default_filter, v8::IndexFilter::kSkipIndices)
|
||||||
|
.ToLocalChecked();
|
||||||
|
const char* expected_properties2[] = {"a", "b", "c", "d"};
|
||||||
|
CheckStringArray(isolate, properties, 4, expected_properties2);
|
||||||
|
|
||||||
|
properties = object
|
||||||
|
->GetPropertyNames(context.local(),
|
||||||
|
v8::KeyCollectionMode::kIncludePrototypes,
|
||||||
|
include_symbols_filter,
|
||||||
|
v8::IndexFilter::kSkipIndices)
|
||||||
|
.ToLocalChecked();
|
||||||
|
const char* expected_properties2_1[] = {"a", "b", nullptr, "c", "d"};
|
||||||
|
CheckStringArray(isolate, properties, 5, expected_properties2_1);
|
||||||
|
CheckIsSymbolAt(isolate, properties, 2, "symbol");
|
||||||
|
|
||||||
|
properties =
|
||||||
|
object
|
||||||
|
->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
|
||||||
|
default_filter, v8::IndexFilter::kIncludeIndices)
|
||||||
|
.ToLocalChecked();
|
||||||
|
const char* expected_properties3[] = {"0", "1", "a", "b"};
|
||||||
|
CheckStringArray(isolate, properties, 4, expected_properties3);
|
||||||
|
|
||||||
|
properties = object
|
||||||
|
->GetPropertyNames(
|
||||||
|
context.local(), v8::KeyCollectionMode::kOwnOnly,
|
||||||
|
include_symbols_filter, v8::IndexFilter::kIncludeIndices)
|
||||||
|
.ToLocalChecked();
|
||||||
|
const char* expected_properties3_1[] = {"0", "1", "a", "b", nullptr};
|
||||||
|
CheckStringArray(isolate, properties, 5, expected_properties3_1);
|
||||||
|
CheckIsSymbolAt(isolate, properties, 4, "symbol");
|
||||||
|
|
||||||
|
properties =
|
||||||
|
object
|
||||||
|
->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
|
||||||
|
default_filter, v8::IndexFilter::kSkipIndices)
|
||||||
|
.ToLocalChecked();
|
||||||
|
const char* expected_properties4[] = {"a", "b"};
|
||||||
|
CheckStringArray(isolate, properties, 2, expected_properties4);
|
||||||
|
|
||||||
|
properties = object
|
||||||
|
->GetPropertyNames(
|
||||||
|
context.local(), v8::KeyCollectionMode::kOwnOnly,
|
||||||
|
include_symbols_filter, v8::IndexFilter::kSkipIndices)
|
||||||
|
.ToLocalChecked();
|
||||||
|
const char* expected_properties4_1[] = {"a", "b", nullptr};
|
||||||
|
CheckStringArray(isolate, properties, 3, expected_properties4_1);
|
||||||
|
CheckIsSymbolAt(isolate, properties, 2, "symbol");
|
||||||
|
}
|
||||||
|
|
||||||
|
THREADED_TEST(ProxyGetPropertyNames) {
|
||||||
|
LocalContext context;
|
||||||
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
v8::Local<v8::Value> result = CompileRun(
|
||||||
|
"var target = {0: 0, 1: 1, a: 2, b: 3};"
|
||||||
|
"target[Symbol('symbol')] = true;"
|
||||||
|
"target.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
|
||||||
|
"var result = new Proxy(target, {});"
|
||||||
"result;");
|
"result;");
|
||||||
v8::Local<v8::Object> object = result.As<v8::Object>();
|
v8::Local<v8::Object> object = result.As<v8::Object>();
|
||||||
v8::PropertyFilter default_filter =
|
v8::PropertyFilter default_filter =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user