exuanbo / module-from-string

Load module from string using require or import.
MIT License
49 stars 2 forks source link

Objects from imported modules have different core types, making instanceof useless #16

Open phorks opened 2 years ago

phorks commented 2 years ago

The instanceof operator always returns false when used with the values from imported modules.

const moduleFromString = require("module-from-string");

const code = "throw new Error();";

try {
  const x = moduleFromString.requireFromString(code);
} catch (err) {
  console.log(Object.getPrototypeOf(err).name === Error.prototype.name);
  console.log(err instanceof Error);
  console.log(err instanceof Object);
}

It outputs:

Or:

const moduleFromString = require("module-from-string");

const code = "exports.obj = {}";

const x = moduleFromString.requireFromString(code);
console.log(Object.getPrototypeOf(x.obj).name === Object.prototype.name);
console.log(x.obj instanceof Object);

Outputs:

Using importFromString yields the same results. It's a side effect of using runInNewContext instead of runInThisContext (or providing context in case of the vm.Module). If this behavior is not intentional, I would be glad to fix it.

exuanbo commented 2 years ago

This is intentional, but I have added an option useCurrentGlobal and some factory functions createRequireFromString etc. in the pre-released version 3.2.0-0. You can install it and give it a try.

If it works well, I will update the README and publish a new minor version tomorrow.

exuanbo commented 2 years ago

Please use the newly added option useCurrentGlobal in 3.2.0.

phorks commented 2 years ago

Thank you. Just a question about the implementation though, did you consider the compileFunction approach that the default nodejs cjs loader takes (here)? That way, there would be no need to shallow copy the entire global object each time.

exuanbo commented 2 years ago

Thank you for the suggestion, I haven't actually considered this approach.

I will try refactoring the code in the next few days.