Skip to content

[Node v20] assert.deepEqual doesn't detect two different URLs #50836

Description

@regseb

Version

v20.9.0

Platform

Linux regseblaptop 6.2.0-36-generic #37~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Oct 9 15:34:04 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

  • create file index.js:

    const assert = require("node:assert/strict");
    
    const url1 = new URL("http://foo1.com/");
    const url2 = new URL("http://foo2.com/");
    assert.deepEqual(url1, url2);
  • node index.js

How often does it reproduce? Is there a required condition?

Always.

What is the expected behavior? Why is that the expected behavior?

The index.js script must raise an error because the two URLs are different.

What do you see instead?

No error.

Additional information

  • npx node@18 index.js

    node:assert:125
      throw new AssertionError(obj);
      ^
    
    AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
    + actual - expected ... Lines skipped
    
      URL {
        [Symbol(context)]: URLContext {
          hash_start: 4294967295,
          host_end: 15,
          host_start: 7,
    +     href: 'http://foo1.com/',
    -     href: 'http://foo2.com/',
          pathname_start: 15,
    ...
          username_end: 7
        }
      }
        at Object.<anonymous> (/home/regseb/testcase/index.js:5:8)
        at Module._compile (node:internal/modules/cjs/loader:1256:14)
        at Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
        at Module.load (node:internal/modules/cjs/loader:1119:32)
        at Module._load (node:internal/modules/cjs/loader:960:12)
        at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:86:12)
        at node:internal/main/run_main_module:23:47 {
      generatedMessage: true,
      code: 'ERR_ASSERTION',
      actual: URL {
        [Symbol(context)]: URLContext {
          href: 'http://foo1.com/',
          protocol_end: 5,
          username_end: 7,
          host_start: 7,
          host_end: 15,
          pathname_start: 15,
          search_start: 4294967295,
          hash_start: 4294967295,
          port: 4294967295,
          scheme_type: 0
        }
      },
      expected: URL {
        [Symbol(context)]: URLContext {
          href: 'http://foo2.com/',
          protocol_end: 5,
          username_end: 7,
          host_start: 7,
          host_end: 15,
          pathname_start: 15,
          search_start: 4294967295,
          hash_start: 4294967295,
          port: 4294967295,
          scheme_type: 0
        }
      },
      operator: 'deepStrictEqual'
    }
    
    Node.js v18.18.2
    

Activity

  1. marco-ippolito commented on Nov 21, 2023

    @marco-ippolito
  2. changed the title [-][Node v20] assert.deepEqual doesn't detect two different URLs[/-] [+][Node v18] assert.deepEqual doesn't detect two different URLs[/+] on Nov 21, 2023
  3. regseb commented on Nov 21, 2023

    @regseb
    ContributorAuthor

    The two URLs are different.

    • With Node v18, assert.deepEqual shows that there is a difference.
    • With Node v20, assert.deepEqual doesn't return an error, although the URLs aren't equal.

    It works in v18 and the bug is in v20.

  4. changed the title [-][Node v18] assert.deepEqual doesn't detect two different URLs[/-] [+][Node v20] assert.deepEqual doesn't detect two different URLs[/+] on Nov 21, 2023
  5. marco-ippolito commented on Nov 21, 2023

    @marco-ippolito
    Member
  6. BridgeAR commented on Nov 21, 2023

    @BridgeAR
    Member

    The difference is not about assert. It's about URL changing the properties of the object. In Node.js 18 the symbol was enumerable and therefore it was compared by assert. But the URL object changed in the meanwhile.

  7. climba03003 commented on Nov 21, 2023

    @climba03003
    Contributor

    I believe it is closely related to #46904 which changing the symbol to private property.
    assert.deepEqual only compare the enumerable properties, so it no longer able to check that symbol property.

    Will it be acceptable to check like Date in here, and create an dedicated checking for URL object?

    } else if (isDate(val1)) {
    if (!isDate(val2) ||
    DatePrototypeGetTime(val1) !== DatePrototypeGetTime(val2)) {
    return false;
    }
    } else if (isRegExp(val1)) {
    if (!isRegExp(val2) || !areSimilarRegExps(val1, val2)) {
    return false;
    }
    } else if (isArrayBufferView(val1)) {
    if (TypedArrayPrototypeGetSymbolToStringTag(val1) !==
    TypedArrayPrototypeGetSymbolToStringTag(val2)) {
    return false;
    }
    if (!strict && (isFloat32Array(val1) || isFloat64Array(val1))) {
    if (!areSimilarFloatArrays(val1, val2)) {
    return false;
    }
    } else if (!areSimilarTypedArrays(val1, val2)) {
    return false;
    }

  8. regseb commented on Mar 7, 2024

    @regseb
    ContributorAuthor

    The util.isDeepStrictEqual(val1, val2) method has the same problem (probably because it uses the same code).

    const util = require("node:util");
    
    const url1 = new URL("http://foo1.com/");
    const url2 = new URL("http://foo2.com/");
    console.log(util.isDeepStrictEqual(url1, url2));
    // true
  9. regseb commented on Oct 1, 2024

    @regseb
    ContributorAuthor

    FYI There's the same problem with Promise. #55198 (comment)

    import assert from 'node:assert/strict';
    
    const promise1 = Promise.resolve("foo");
    const promise2 = Promise.resolve("bar");
    assert.deepEqual(promise1, promise2);
  10. added a commit that references this issue on Oct 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues and PRs for confirmed bugs.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions