fix: support canonical module#5040
Conversation
| }); | ||
|
|
||
| it('should represent modules', async function () { | ||
| if (process.browser) { |
There was a problem hiding this comment.
The esm-utils and node:path modules both come through as undefined in browser (which is kinda expected).
In theory though, it probably isn't necessary to use esm-utils at all, and the path logic we are using is just a very basic join, which we can probably safely default to __dirname + '/fixtures/module.mjs' and load via a dynamic import import() (Maybe keep the path module around for node+windows support)
However, it appears the current version of rollup has issues parsing that. It appears rollup is ~2 major versions out of date, so I wouldn't be surprised if it just isn't equipped to handle "modern" js syntax.
I tried bumping rollup version and it was not straightforward. I'm sure someone with more rollup experience can easily knock it out, but it felt out of scope for what I was trying to achieve with this fix.
|
Updated original ticket with better reproduction: #4887 Still open to alternative approaches to handle the "this should only run as part of serverside tests", but that is more on the testing front rather than the implementation. |
| break; | ||
| } | ||
| /* falls through */ | ||
| case 'module': |
There was a problem hiding this comment.
With a bit more manual testing (when trying to reproduce) I think this issue may fundamentally occur anytime you are dealing with null-prototyped instances...
Which is an overall rare occurrence, but maybe this isn't the right approach?
e.g.
const foo = Object.create(null, {
[Symbol.toStringTag]: { value: 'Foo' },
bing: { get: () => 'bong' }
});
Object.prototype.toString.call(x); // '[object Foo]'
foo + ''; // Uncaught TypeError: Cannot convert object to primitive value
So while this solution works for modules, I don't think it actually solves the underlying issue
| }); | ||
| const expected = [ | ||
| '{', | ||
| ' "[Symbol.toStringTag]": "Foo"', |
There was a problem hiding this comment.
If we wanted to either:
- Always expose the
toStringTagif present - Never expose the
toStringTag
Then we could just return object instead of null-prototype and the logic would work.
Only really need a special case if we are conditionally exposing it...
There was a problem hiding this comment.
I don't have a strong preference either way. What's working now fixes the issue and is nicely informative on my end.
| } else if ( | ||
| typeof value === 'object' && | ||
| // eslint-disable-next-line no-prototype-builtins | ||
| !Object.prototype.isPrototypeOf(value) | ||
| ) { |
There was a problem hiding this comment.
We can probably do this instead? And avoid having to opt out of the eslint rules?
| } else if ( | |
| typeof value === 'object' && | |
| // eslint-disable-next-line no-prototype-builtins | |
| !Object.prototype.isPrototypeOf(value) | |
| ) { | |
| } else if (Object.getPrototypeOf(value) === null) { |
There was a problem hiding this comment.
Yup that is cleaner, pushed a small update
|
Released in |
* fix: handle canonicalizing Module * fix: add tests for canonicalizing a module * fix: skip module serialization on browser * fix: handle more generic null prototype instead of Module * fix: simplify null prototype check
ORIGINAL PR: #4888
Closed out of staleness, but now trying to re-open under new maintenance
Description of the Change
Handle canonicalizing Module, prevent implicit stringification failures
Alternate Designs
Why should this be in core?
Current module canonicalization is broken, see #4887
Benefits
Tests can properly handle errors with a Module inside
Possible Drawbacks
Small chance there is some internal/custom handling expecting canonicalization of modules to fail... Seems unlikely?
Applicable issues
Fixes #4887
Bug fix, patch release