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

import(data:text/javascript,) throw SyntaxError #42504

Closed
lovetingyuan opened this issue Mar 28, 2022 · 8 comments
Closed

import(data:text/javascript,) throw SyntaxError #42504

lovetingyuan opened this issue Mar 28, 2022 · 8 comments

Comments

@lovetingyuan
Copy link

lovetingyuan commented Mar 28, 2022

Version

v16.14.2

Platform

Darwin tingyuandeMacBook-Pro.local 21.1.0 Darwin Kernel Version 21.1.0: Wed Oct 13 17:33:23 PDT 2021; root:xnu-8019.41.5~1/RELEASE_X86_64 x86_64

Subsystem

No response

What steps will reproduce the bug?

const c = `
var config0 = {
  text: '{{ a => a === "aa" ? "bb" : "cc" }}'
};
var _configs = { "aa": config0 };
var configFiles = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  "default": _configs
}, Symbol.toStringTag, { value: "Module" }));
export { configFiles as default };
`;
import(`data:text/javascript,${c}`).then((res) => {
  console.log(res);
});

Just run the code with latest node, error is here:

data:text/javascript,var config0 = {  text: '{{ a => a === "aa" ?%20%22bb%22%20:%20%22cc%22%20}}'};var%20_configs%20=%20{%20%22aa%22:%20config0%20};var%20configFiles%20=%20/*%20@__PURE__%20*/%20Object.freeze(/*%20@__PURE__%20*/%20Object.defineProperty({%20%20__proto__:%20null,%20%20%22default%22:%20_configs},%20Symbol.toStringTag,%20{%20value:%20%22Module%22%20}));export%20{%20configFiles%20as%20default%20};:1
var config0 = {  text: '{{ a => a === "aa" 
                       ^^^^^^^^^^^^^^^^^^^^

SyntaxError: Invalid or unexpected token
    at ESMLoader.moduleStrategy (node:internal/modules/esm/translators:115:18)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:289:14)
    at async link (node:internal/modules/esm/module_job:70:21)

but, in chrome, the code runs well, no error.
image

How often does it reproduce? Is there a required condition?

100% reproduce.

What is the expected behavior?

no error should be thrown, It seems related to ?(ternary operator).

What do you see instead?

node can not run the code, but chrome can run the same code.

Additional information

No response

@lovetingyuan
Copy link
Author

A simpler example is here:

const c = "const a = '?' === false;";
import(`data:text/javascript,${c}`).then((res) => {
  console.log(res);
});

@aduh95
Copy link
Contributor

aduh95 commented Mar 28, 2022

Yep, it looks like Node.js is acting differently than other JS runtimes. //cc @nodejs/loaders

FWIW, you can workaround this by encoding special URL characters:

const c = "const a = '?' === false;";
import(`data:text/javascript,${encodeURIComponent(c)}`).then((res) => {
  console.log(res);
});

@bmeck
Copy link
Member

bmeck commented Mar 28, 2022

Please encode special components and/or use base64 support in your data: URIs for cross environment stability, Firefox also fails in this case:

image

This failure is caused by a disagreement on if query parameters are valid on data: URIs. I'd note that according to new URL() everything after the ? is a query parameter and is the main reason this behavior is as Node implemented it.

@lovetingyuan
Copy link
Author

Yep, it looks like Node.js is acting differently than other JS runtimes. //cc @nodejs/loaders

FWIW, you can workaround this by encoding special URL characters:

const c = "const a = '?' === false;";
import(`data:text/javascript,${encodeURIComponent(c)}`).then((res) => {
  console.log(res);
});

Thanks, It works on node16, but still failed on node14, but with base64 format, both will work well, like this:

const c = "const a = '?' === false;";
import(`data:text/javascript;base64,${Buffer.from(c).toString('base64')}`).then((res) => {
  console.log(res);
});

@aduh95
Copy link
Contributor

aduh95 commented Mar 29, 2022

Yep, it looks like Node.js is acting differently than other JS runtimes. //cc @nodejs/loaders
FWIW, you can workaround this by encoding special URL characters:

const c = "const a = '?' === false;";
import(`data:text/javascript,${encodeURIComponent(c)}`).then((res) => {
  console.log(res);
});

Thanks, It works on node16, but still failed on node14, but with base64 format, both will work well, like this:

const c = "const a = '?' === false;";
import(`data:text/javascript;base64,${Buffer.from(c).toString('base64')}`).then((res) => {
  console.log(res);
});

I think the fix was already backported to v14.18.0 (98259dc). Are you testing on an up-to-date version?

@lovetingyuan
Copy link
Author

Yep, it looks like Node.js is acting differently than other JS runtimes. //cc @nodejs/loaders
FWIW, you can workaround this by encoding special URL characters:

const c = "const a = '?' === false;";
import(`data:text/javascript,${encodeURIComponent(c)}`).then((res) => {
  console.log(res);
});

Thanks, It works on node16, but still failed on node14, but with base64 format, both will work well, like this:

const c = "const a = '?' === false;";
import(`data:text/javascript;base64,${Buffer.from(c).toString('base64')}`).then((res) => {
  console.log(res);
});

I think the fix was already backported to v14.18.0 (98259dc). Are you testing on an up-to-date version?

yes yes, 14.18.0 is ok,👍 (the error occurs on 14.17.1)

@lovetingyuan
Copy link
Author

The problem is solved, if there is no other questions, I will close this issue after a few days. Thank you very much.

@lovetingyuan
Copy link
Author

The problem is solved, if there is no other questions, I will close this issue after a few days. Thank you very much.

Always use encodeURIComponent with source code string in dynamic importing data url, and better to avoid using this(not a best practice)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants