diff options
author | Ruben Bridgewater <ruben@bridgewater.de> | 2018-08-08 03:43:20 +0200 |
---|---|---|
committer | Ruben Bridgewater <ruben@bridgewater.de> | 2018-08-13 12:00:36 +0200 |
commit | c4007f0096e3a1e777faea35a35e849513e33a89 (patch) | |
tree | a38d2cea8b50b4b7768e8dbf6f618cd53ff744ae /deps | |
parent | 5442c28b651a79c2269bf2b931e81cd553171656 (diff) | |
download | node-new-c4007f0096e3a1e777faea35a35e849513e33a89.tar.gz |
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>
Diffstat (limited to 'deps')
-rw-r--r-- | deps/v8/src/keys.cc | 46 | ||||
-rw-r--r-- | deps/v8/src/keys.h | 14 | ||||
-rw-r--r-- | deps/v8/src/runtime/runtime-forin.cc | 3 | ||||
-rw-r--r-- | deps/v8/test/cctest/test-api.cc | 97 |
4 files changed, 135 insertions, 25 deletions
diff --git a/deps/v8/src/keys.cc b/deps/v8/src/keys.cc index 98226ae8b7..0213ae0619 100644 --- a/deps/v8/src/keys.cc +++ b/deps/v8/src/keys.cc @@ -37,10 +37,10 @@ static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { // static MaybeHandle<FixedArray> KeyAccumulator::GetKeys( 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(); - FastKeyAccumulator accumulator(isolate, object, mode, filter); - accumulator.set_is_for_in(is_for_in); + FastKeyAccumulator accumulator(isolate, object, mode, filter, is_for_in, + skip_indices); return accumulator.GetKeys(keys_conversion); } @@ -356,7 +356,8 @@ Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate, template <bool fast_properties> MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate, Handle<JSObject> object, - GetKeysConversion convert) { + GetKeysConversion convert, + bool skip_indices) { Handle<FixedArray> keys; ElementsAccessor* accessor = object->GetElementsAccessor(); if (fast_properties) { @@ -365,8 +366,13 @@ MaybeHandle<FixedArray> GetOwnKeysWithElements(Isolate* isolate, // TODO(cbruni): preallocate big enough array to also hold elements. keys = KeyAccumulator::GetOwnEnumPropertyKeys(isolate, object); } - MaybeHandle<FixedArray> result = - accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE); + MaybeHandle<FixedArray> result; + if (skip_indices) { + result = keys; + } else { + result = + accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE); + } if (FLAG_trace_for_in_enumerate) { 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. 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(); if (enum_length == kInvalidEnumCacheSentinel) { @@ -422,7 +429,8 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast( } // The properties-only case failed because there were probably elements on the // receiver. - return GetOwnKeysWithElements<true>(isolate_, object, keys_conversion); + return GetOwnKeysWithElements<true>(isolate_, object, keys_conversion, + skip_indices_); } MaybeHandle<FixedArray> @@ -451,6 +459,7 @@ MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow( GetKeysConversion keys_conversion) { KeyAccumulator accumulator(isolate_, mode_, filter_); accumulator.set_is_for_in(is_for_in_); + accumulator.set_skip_indices(skip_indices_); accumulator.set_last_non_empty_prototype(last_non_empty_prototype_); MAYBE_RETURN(accumulator.CollectKeys(receiver_, receiver_), @@ -698,13 +707,15 @@ Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver, Maybe<bool> KeyAccumulator::CollectAccessCheckInterceptorKeys( Handle<AccessCheckInfo> access_check_info, Handle<JSReceiver> receiver, Handle<JSObject> object) { - MAYBE_RETURN((CollectInterceptorKeysInternal( - receiver, object, - handle(InterceptorInfo::cast( - access_check_info->indexed_interceptor()), - isolate_), - this, kIndexed)), - Nothing<bool>()); + if (!skip_indices_) { + MAYBE_RETURN((CollectInterceptorKeysInternal( + receiver, object, + handle(InterceptorInfo::cast( + access_check_info->indexed_interceptor()), + isolate_), + this, kIndexed)), + Nothing<bool>()); + } MAYBE_RETURN( (CollectInterceptorKeysInternal( receiver, object, @@ -935,8 +946,9 @@ Maybe<bool> KeyAccumulator::CollectOwnJSProxyTargetKeys( Handle<FixedArray> keys; ASSIGN_RETURN_ON_EXCEPTION_VALUE( isolate_, keys, - KeyAccumulator::GetKeys(target, KeyCollectionMode::kOwnOnly, filter_, - GetKeysConversion::kConvertToString, is_for_in_), + KeyAccumulator::GetKeys( + target, KeyCollectionMode::kOwnOnly, filter_, + GetKeysConversion::kConvertToString, is_for_in_, skip_indices_), Nothing<bool>()); Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); return result; diff --git a/deps/v8/src/keys.h b/deps/v8/src/keys.h index 649d6a9599..5abbaac5cd 100644 --- a/deps/v8/src/keys.h +++ b/deps/v8/src/keys.h @@ -40,7 +40,7 @@ class KeyAccumulator final BASE_EMBEDDED { static MaybeHandle<FixedArray> GetKeys( Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter, GetKeysConversion keys_conversion = GetKeysConversion::kKeepNumbers, - bool is_for_in = false); + bool is_for_in = false, bool skip_indices = false); Handle<FixedArray> GetKeys( GetKeysConversion convert = GetKeysConversion::kKeepNumbers); @@ -128,14 +128,19 @@ class KeyAccumulator final BASE_EMBEDDED { class FastKeyAccumulator { public: FastKeyAccumulator(Isolate* isolate, Handle<JSReceiver> receiver, - KeyCollectionMode mode, PropertyFilter filter) - : isolate_(isolate), receiver_(receiver), mode_(mode), filter_(filter) { + KeyCollectionMode mode, PropertyFilter 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(); } bool is_receiver_simple_enum() { return is_receiver_simple_enum_; } bool has_empty_prototype() { return has_empty_prototype_; } - void set_is_for_in(bool value) { is_for_in_ = value; } MaybeHandle<FixedArray> GetKeys( GetKeysConversion convert = GetKeysConversion::kKeepNumbers); @@ -153,6 +158,7 @@ class FastKeyAccumulator { KeyCollectionMode mode_; PropertyFilter filter_; bool is_for_in_ = false; + bool skip_indices_ = false; bool is_receiver_simple_enum_ = false; bool has_empty_prototype_ = false; diff --git a/deps/v8/src/runtime/runtime-forin.cc b/deps/v8/src/runtime/runtime-forin.cc index 9193daf9db..58e47f621e 100644 --- a/deps/v8/src/runtime/runtime-forin.cc +++ b/deps/v8/src/runtime/runtime-forin.cc @@ -25,8 +25,7 @@ MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) { JSObject::MakePrototypesFast(receiver, kStartAtReceiver, isolate); FastKeyAccumulator accumulator(isolate, receiver, KeyCollectionMode::kIncludePrototypes, - ENUMERABLE_STRINGS); - accumulator.set_is_for_in(true); + ENUMERABLE_STRINGS, true); // Test if we have an enum cache for {receiver}. if (!accumulator.is_receiver_simple_enum()) { Handle<FixedArray> keys; diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 366b940d61..5bea5b14d0 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -15356,14 +15356,107 @@ THREADED_TEST(PropertyEnumeration2) { } } -THREADED_TEST(PropertyNames) { +THREADED_TEST(GetPropertyNames) { LocalContext context; v8::Isolate* isolate = context->GetIsolate(); v8::HandleScope scope(isolate); v8::Local<v8::Value> result = CompileRun( "var result = {0: 0, 1: 1, a: 2, b: 3};" "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;"); v8::Local<v8::Object> object = result.As<v8::Object>(); v8::PropertyFilter default_filter = |