nodejs / import-in-the-middle

Like `require-in-the-middle`, but for ESM import
https://www.npmjs.com/package/import-in-the-middle
Apache License 2.0
67 stars 24 forks source link

Assignments to exported variables are not visible in other modules #38

Open dennisjlee opened 10 months ago

dennisjlee commented 10 months ago

Expected Behavior

If a module exports a variable that was defined with let and can be reassigned, other modules that import that variable should always see the current value of the variable.

E.g.

env.js:

let env = { FOO: 'baz' };   // Starts with an old value

function setEnv(newEnv) {
  // Allow callers to set a new value
  env = newEnv;
}

export { env, setEnv };

If module1 calls setEnv with a new value, and module2 references env, module2 should see the new value.

Actual Behavior

With the Node flag --experimental-loader=import-in-the-middle/hook.mjs, module2 actually sees the old value.

Steps to Reproduce the Problem

I made a repro here: https://github.com/dennisjlee/iitm-assign-module-var-repro

Specifications

timfish commented 3 months ago

Because the iitm wrappers assign each export to a variable before re-exporting, primitive exports have their original value copied and the reference is lost.

This is where the code generation does that: https://github.com/nodejs/import-in-the-middle/blob/57d2459748492abd55e04a679d8b5752b90dfab4/hook.js#L189-L190

Possible solutions/workarounds? I dont think there's much we can actually do to fix this.

dennisjlee commented 3 months ago

@timfish I encountered this issue when working with a SvelteKit application. I was trying to update our NewRelic Node.js agent to a more recent version; NewRelic switched to using import-in-the-middle to instrument module loading in v11 (release notes).

When I was testing that setup with the SvelteKit app, this turned out to be a blocking bug because of this module in SvelteKit that relies on reassigning exported symbols, like my simplified repro above.

With that said, I am no longer working on that project so this is no longer important to me personally, but I expect that this issue could affect other users of import-in-the-middle via instrumentation tools like NewRelic or DataDog, depending on the libraries/frameworks they need to import.