swc-project / swc-node

Faster ts-node without typecheck
MIT License
1.81k stars 76 forks source link

Register not compiling TS files with URL specifier #794

Closed psychobolt closed 4 months ago

psychobolt commented 5 months ago

Updated to @swc-node/register v1.10.0

I have a file imported in one of my sub-packages using the following url specifier path with query e.g. import(`my/project/foo.ts?${timestamp}`) . However, seems like my compiled output is same as original source in debug inspection. This led to my vite plugin to throw SyntaxError e.g.

SyntaxError: Unexpected token '{'
    at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:169:18)
    at callTranslator (node:internal/modules/esm/loader:272:14)
    at ModuleLoader.moduleProvider (node:internal/modules/esm/loader:278:30)
    at async link (node:internal/modules/esm/module_job:78:21)

log ref

Changingurl to filePath usingfileURLtoPath, seems to resolve my main issue. e.g.

diff --git a/esm/esm.mjs b/esm/esm.mjs
index 1e7429abec21338477f904b17a35161b75d01e19..9bfcf808525a89651bc69833259c1b520d09b568 100644
--- a/esm/esm.mjs
+++ b/esm/esm.mjs
@@ -178,7 +178,7 @@ export const load = async (url, context, nextLoad) => {
     const { source, format: resolvedFormat } = await nextLoad(url, context);
     debug('loaded', url, resolvedFormat);
     const code = !source || typeof source === 'string' ? source : Buffer.from(source).toString();
-    const compiled = await compile(code, url, tsconfigForSWCNode, true);
+    const compiled = await compile(code, url.startsWith('file:') ? fileURLToPath(url) : url, tsconfigForSWCNode, true);
     debug('compiled', url, resolvedFormat);
     return addShortCircuitSignal({
         // for lazy: ts-node think format would undefined, actually it should not, keep it as original temporarily

However, after applying the above suggested fix, I would get another error which seems to only fail on Windows:

[SB] TypeError [ERR_INVALID_RETURN_PROPERTY_VALUE]: Expected undefined or a fully resolved URL string to be returned for the "responseURL" from the "node:internal/modules/esm/load 'load'" hook but got type string ('file://D:/a/vite-storyboo...').
[SB]     at Hooks.load (node:internal/modules/esm/hooks:480:13)
[SB]     at async handleMessage (node:internal/modules/esm/worker:196:18) {
[SB]   code: 'ERR_INVALID_RETURN_PROPERTY_VALUE'

Expected Behavior

All TS files with URL specifier should be compiled and resolved without any issues.

psychobolt commented 5 months ago

Didn't look into too deeply, but I suspect on Windows the file url would be backslash'd and have a lowercase drive letter. Since there is a check here, I simply patched the url before short circuit is sent e.g.

     return addShortCircuitSignal({
         // for lazy: ts-node think format would undefined, actually it should not, keep it as original temporarily
         format: resolvedFormat,
         source: compiled,
+        responseURL: new URL(url).href
     });
 };
yeliex commented 5 months ago

could you please provide a minimal reproduction

psychobolt commented 5 months ago

https://codesandbox.io/p/devbox/swc-register-import-query-gq2hpq . If you run this sandbox you will get ERR_UNKNOWN_FILE_EXTENSION for query import. However if I prefix with file:// to import, there is no issues.