-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
assert.deepEqual
and assert.deepStrictEqual
incorrectly compare Proxied arrays when using ownKeys
trap
#41714
Comments
@nodejs/assert |
This comment was marked as off-topic.
This comment was marked as off-topic.
Hmm
So the issue is that 0 is considered an index property. So the issue is that
Does not ignore index properties with a proxy trap? |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
@ljharb it wouldn't matter in this case:
This is a "bug" either in v8 or how we use v8 which returns index properties from the call above. (I saw bug because I don't believe we ever discussed what proxy behavior should be) |
@ljharb, The problem still occurs with passing assert.deepEqual(new Proxy(['foo'], { ownKeys: Reflect.ownKeys }), ['foo']) // throws I see in the spec that you're right, it should be passing a |
This comment was marked as off-topic.
This comment was marked as off-topic.
A fix can be something like this: diff --git a/lib/internal/util/comparisons.js b/lib/internal/util/comparisons.js
index c126bd6346..6a529c100f 100644
--- a/lib/internal/util/comparisons.js
+++ b/lib/internal/util/comparisons.js
@@ -36,6 +36,7 @@ const {
isRegExp,
isSet,
isNativeError,
+ isProxy,
isBoxedPrimitive,
isNumberObject,
isStringObject,
@@ -68,6 +69,14 @@ function areSimilarRegExps(a, b) {
a.lastIndex === b.lastIndex;
}
+function getOwnNonIndexPropertiesHandleProxies(target, filter) {
+ const res = getOwnNonIndexProperties(target, filter);
+ if (isProxy(target)) {
+ return res.filter((x) => typeof x !== 'number');
+ }
+ return res;
+}
+
function areSimilarFloatArrays(a, b) {
if (a.byteLength !== b.byteLength) {
return false;
@@ -176,8 +185,8 @@ function innerDeepEqual(val1, val2, strict, memos) {
return false;
}
const filter = strict ? ONLY_ENUMERABLE : ONLY_ENUMERABLE | SKIP_SYMBOLS;
- const keys1 = getOwnNonIndexProperties(val1, filter);
- const keys2 = getOwnNonIndexProperties(val2, filter);
+ const keys1 = getOwnNonIndexPropertiesHandleProxies(val1, filter);
+ const keys2 = getOwnNonIndexPropertiesHandleProxies(val2, filter);
if (keys1.length !== keys2.length) {
return false;
}
@@ -217,8 +226,8 @@ function innerDeepEqual(val1, val2, strict, memos) {
// only contain numeric keys, we don't need to exam further than checking
// the symbols.
const filter = strict ? ONLY_ENUMERABLE : ONLY_ENUMERABLE | SKIP_SYMBOLS;
- const keys1 = getOwnNonIndexProperties(val1, filter);
- const keys2 = getOwnNonIndexProperties(val2, filter);
+ const keys1 = getOwnNonIndexPropertiesHandleProxies(val1, filter);
+ const keys2 = getOwnNonIndexPropertiesHandleProxies(val2, filter);
if (keys1.length !== keys2.length) {
return false;
} We should also probably file a v8 bug? |
Wouldn’t that fix potentially interfere with proxies of arrays, or proxies of objects with numeric string keys? |
It would as in today they don't work and following this patch they do and return the same keys as the non-proxy version |
|
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
@ljharb the issue is much simpler than that I think? no one updated the assert code to support proxies and there are (likely) a bunch of bugs in the V8 APIs used like Gus said. So I think this feature request is definitely worth doing but am waiting for someone with more regular commits to V8 to either fix it there or tell us it's intended so we work around it similar to #41714 (comment) Note node is not distinguishing something based on whether or not it's a proxy in that workaround - it just works around the underlying v8 bug that does. |
@benjamingr sure, there's surely something to fix here. What I meant is, node's inspection output in the thrown assertion error clearly marks the proxy as a Proxy; that's the part i was saying is a violation of the language's intent. |
Yes though that's not intentional it's just since assert was never made to work with proxies. This is a v8 bug not something intentional Node chose to do. |
This comment was marked as off-topic.
This comment was marked as off-topic.
I had trouble seeing the comments that were directly related to the issue, so I just hid some comments as off-topic. @nodejs/v8 the issue here clearly looks like a V8 bug. Would it be possible to fix |
There is actually an explicit comment about the behavior in V8: node/deps/v8/src/objects/keys.h Lines 33 to 37 in dabda03
We could either implement the behavior in FilterProxyKeys or have to check for proxies on our own and do the filtering manually as @benjamingr suggested. node/deps/v8/src/objects/keys.cc Lines 182 to 213 in dabda03
|
It is actually somewhat confusing for me that there's a separate |
What should we do with this? |
I opened https://bugs.chromium.org/p/v8/issues/detail?id=13728. Let's see if this can be fixed in V8. |
I tried a solution something like diff --git a/deps/v8/src/objects/keys.cc b/deps/v8/src/objects/keys.cc
index a0796864f1..4f84cd9094 100644
--- a/deps/v8/src/objects/keys.cc
+++ b/deps/v8/src/objects/keys.cc
@@ -182,8 +182,9 @@ ExceptionStatus KeyAccumulator::AddKeys(Handle<JSObject> array_like,
MaybeHandle<FixedArray> FilterProxyKeys(KeyAccumulator* accumulator,
Handle<JSProxy> owner,
Handle<FixedArray> keys,
- PropertyFilter filter) {
- if (filter == ALL_PROPERTIES) {
+ PropertyFilter filter,
+ bool skip_indices) {
+ if (filter == ALL_PROPERTIES && !skip_indices) {
// Nothing to do.
return keys;
}
@@ -191,7 +192,7 @@ MaybeHandle<FixedArray> FilterProxyKeys(KeyAccumulator* accumulator,
int store_position = 0;
for (int i = 0; i < keys->length(); ++i) {
Handle<Name> key(Name::cast(keys->get(i)), isolate);
- if (key->FilterKey(filter)) continue; // Skip this key.
+ if (key->FilterKey(filter) || (skip_indices && key->IsNumber())) continue; // Skip this key.
if (filter & ONLY_ENUMERABLE) {
PropertyDescriptor desc;
Maybe<bool> found =
@@ -218,7 +219,7 @@ Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy,
// Postpone the enumerable check for for-in to the ForInFilter step.
if (!is_for_in_) {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, keys, FilterProxyKeys(this, proxy, keys, filter_),
+ isolate_, keys, FilterProxyKeys(this, proxy, keys, filter_, skip_indices_),
Nothing<bool>());
}
// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys On v8 but doesn't seem to make a change 😕 |
Hey! was able to get this fixed in v8 @ https://chromium.googlesource.com/v8/v8/+/975ff4dbfd1be3a7395e26d412774bc955b47341 so the next update of v8 in node should fix it or do we have to patch the commit here? |
Original commit message: fix GetPropertyNames for proxys with ownKeys trap Added checks to FilterProxyKeys function for when skip_indices is enabled. Bug: v8:13728 Change-Id: Id096e32ef8e6c2344be9682e8222aea8790bd66d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4333698 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#86548} Refs: v8/v8@975ff4d PR-URL: #47209 Fixes: #41714 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Erick Wendel <erick.workspace@gmail.com>
Original commit message: fix GetPropertyNames for proxys with ownKeys trap Added checks to FilterProxyKeys function for when skip_indices is enabled. Bug: v8:13728 Change-Id: Id096e32ef8e6c2344be9682e8222aea8790bd66d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4333698 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#86548} Refs: v8/v8@975ff4d PR-URL: #47209 Fixes: #41714 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Erick Wendel <erick.workspace@gmail.com>
Original commit message: fix GetPropertyNames for proxys with ownKeys trap Added checks to FilterProxyKeys function for when skip_indices is enabled. Bug: v8:13728 Change-Id: Id096e32ef8e6c2344be9682e8222aea8790bd66d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4333698 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#86548} Refs: v8/v8@975ff4d PR-URL: #47209 Fixes: #41714 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Erick Wendel <erick.workspace@gmail.com>
Original commit message: fix GetPropertyNames for proxys with ownKeys trap Added checks to FilterProxyKeys function for when skip_indices is enabled. Bug: v8:13728 Change-Id: Id096e32ef8e6c2344be9682e8222aea8790bd66d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4333698 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#86548} Refs: v8/v8@975ff4d PR-URL: #47209 Fixes: #41714 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Erick Wendel <erick.workspace@gmail.com>
Original commit message: fix GetPropertyNames for proxys with ownKeys trap Added checks to FilterProxyKeys function for when skip_indices is enabled. Bug: v8:13728 Change-Id: Id096e32ef8e6c2344be9682e8222aea8790bd66d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4333698 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#86548} Refs: v8/v8@975ff4d PR-URL: #47209 Fixes: #41714 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Erick Wendel <erick.workspace@gmail.com>
Version
v17.4.0
Platform
Darwin macbook-pro-5.lan 21.2.0 Darwin Kernel Version 21.2.0: Sun Nov 28 20:28:54 PST 2021; root:xnu-8019.61.5~1/RELEASE_X86_64 x86_64
Subsystem
assert
What steps will reproduce the bug?
In the above,
Reflect.ownKeys(target)
should be the same as not setting anownKeys
trap, but it isn't. The trap works fine elsewhereIndeed,
How often does it reproduce? Is there a required condition?
Every time
What is the expected behavior?
Using a
ownKeys
trap shouldn't cause comparison errors.The
ownKeys
trap seems to be working fine elsewhere. I traced the code to:node/lib/internal/util/comparisons.js
Line 179 in dab8ab2
Where the
GetOwnNonIndexProperties
function is called. Perhaps it is incorrectly filtering or the filtering is broken for proxies somehow?What do you see instead?
Comparison errors from
assert.deepEquals
andassert.deepStrictEquals
when the Arrays compared have the same content, but are using Proxies withownKeys
traps.Additional information
I tried this on node 14, 16, and 17, with the same results.
The text was updated successfully, but these errors were encountered: