Skip to content
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

fix: Skip wrapping CJS modules which result in invalid identifiers #115

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 10 additions & 16 deletions hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

const { URL } = require('url')
const { inspect } = require('util')
const { isIdentifierName } = require('@babel/helper-validator-identifier')
const { builtinModules } = require('module')
const specifiers = new Map()
const isWin = process.platform === 'win32'
Expand Down Expand Up @@ -200,6 +201,10 @@ async function processModule ({ srcUrl, context, parentGetSource, parentResolve,
const setters = new Map()

const addSetter = (name, setter, isStarExport = false) => {
if (!isIdentifierName(name)) {
throw new Error(`'${name}' export is not a valid identifier name`)
}

if (setters.has(name)) {
if (isStarExport) {
// If there's already a matching star export, delete it
Expand Down Expand Up @@ -380,7 +385,8 @@ function createHook (meta) {
}
}

async function getSource (url, context, parentGetSource) {
// For Node.js 16.12.0 and higher.
async function load (url, context, parentGetSource) {
if (hasIitm(url)) {
const realUrl = deleteIitm(url)

Expand All @@ -392,6 +398,8 @@ function createHook (meta) {
parentResolve: cachedResolve
})
return {
shortCircuit: true,
format: 'module',
source: `
import { register } from '${iitmURL}'
import * as namespace from ${JSON.stringify(realUrl)}
Expand Down Expand Up @@ -432,28 +440,14 @@ register(${JSON.stringify(realUrl)}, _, set, ${JSON.stringify(specifiers.get(rea
return parentGetSource(url, context, parentGetSource)
}

// For Node.js 16.12.0 and higher.
async function load (url, context, parentLoad) {
if (hasIitm(url)) {
const { source } = await getSource(url, context, parentLoad)
return {
source,
shortCircuit: true,
format: 'module'
}
}

return parentLoad(url, context, parentLoad)
}

if (NODE_MAJOR >= 17 || (NODE_MAJOR === 16 && NODE_MINOR >= 12)) {
return { initialize, load, resolve }
} else {
return {
initialize,
load,
resolve,
getSource,
getSource: load,
getFormat (url, context, parentGetFormat) {
if (hasIitm(url)) {
return {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"acorn": "^8.8.2",
"acorn-import-attributes": "^1.9.5",
"cjs-module-lexer": "^1.2.2",
"module-details-from-path": "^1.0.3"
"module-details-from-path": "^1.0.3",
"@babel/helper-validator-identifier": "^7.24.7"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to hear from @Qard or @bengl what they think about adding in this dependency.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could vendor this code and it's around 13kB.

This package has 50m weekly downloads so there's a high chance it will already be in many users dependencies.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This package has 50m weekly downloads so there's a high chance it will already be in many users dependencies.

Maybe. But I've never seen the package before this PR. I looked through it back when this PR was opened, and I remember getting the impression that it could be overkill. So I wanted an opinion from the folks much more in tune with this code than I am.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with it, though I wonder if we really need all that and not just a simplified subset of it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need all of identifier.js (12.2kB) which is most of the package.

image

}
}
1 change: 1 addition & 0 deletions test/fixtures/invalid-identifier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports['one.two'] = () => console.log('b')
4 changes: 4 additions & 0 deletions test/hook/invalid-identifier.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as lib from '../fixtures/invalid-identifier.js'
import { strictEqual } from 'assert'

strictEqual(typeof lib['one.two'], 'function')
Loading