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:
Ruben Bridgewater 2018-08-08 03:43:20 +02:00
parent 5442c28b65
commit c4007f0096
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
5 changed files with 136 additions and 26 deletions

View File

@ -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
View File

@ -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
View File

@ -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;

View File

@ -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;

View File

@ -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 =