fix(es/resolver): Resolve top-level undefined, NaN, and Infinity correctly (#8471)

**Description:**

For following code
```js
var NaN = 1
console.log(NaN)
```
Result would be

|Envirnoment|Result|
|-|-|
|Non strict script(browser, nodejs repl)|NaN|
|Non strict script(nodejs script)|1|
|Strict script(browser, nodejs repl)|runtime error|
|Strict script(nodejs script)|1|
|ESM|1|

So SWC choose to behave like browser in script mode and confirm to esm
standard.


**Related issue:**

 - Closes #8465
This commit is contained in:
Austaras 2024-01-04 12:24:14 +08:00 committed by GitHub
parent ce76159e98
commit 82bd8070cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 23 additions and 9 deletions

View File

@ -0,0 +1,4 @@
function Infinity() {
console.log("xxx");
}
export default Infinity;

View File

@ -0,0 +1,3 @@
export default function() {
console.log("xxx");
}

View File

@ -112,12 +112,12 @@ fn terser_exec(input: PathBuf) {
eprintln!("Optimizing");
let output = run(cm.clone(), &handler, &input, &config);
let output_module = match output {
let output_program = match output {
Some(v) => v,
None => return Err(()),
};
let actual = print(cm, &[output_module], false, false);
let actual = print(cm, &[output_program], false, false);
let actual_stdout = stdout_of(&actual, Duration::from_secs(5)).unwrap();
if let Some(expected_src) = expected_src {

View File

@ -148,6 +148,7 @@ pub fn resolver(
current: Scope::new(ScopeKind::Fn, top_level_mark, None),
ident_type: IdentType::Ref,
in_type: false,
is_module: false,
in_ts_module: false,
decl_kind: DeclKind::Lexical,
strict_mode: false,
@ -204,6 +205,7 @@ struct Resolver<'a> {
current: Scope<'a>,
ident_type: IdentType,
in_type: bool,
is_module: bool,
in_ts_module: bool,
decl_kind: DeclKind,
strict_mode: bool,
@ -225,6 +227,7 @@ impl<'a> Resolver<'a> {
current,
ident_type: IdentType::Ref,
in_type: false,
is_module: false,
in_ts_module: false,
config,
decl_kind: DeclKind::Lexical,
@ -245,6 +248,7 @@ impl<'a> Resolver<'a> {
ident_type: IdentType::Ref,
config: self.config,
in_type: self.in_type,
is_module: self.is_module,
in_ts_module: self.in_ts_module,
decl_kind: self.decl_kind,
strict_mode: self.strict_mode,
@ -306,7 +310,9 @@ impl<'a> Resolver<'a> {
return match &**sym {
// https://tc39.es/ecma262/multipage/global-object.html#sec-value-properties-of-the-global-object-infinity
// non configurable global value
"undefined" | "NaN" | "Infinity" if mark == self.config.top_level_mark => {
"undefined" | "NaN" | "Infinity"
if mark == self.config.top_level_mark && !self.is_module =>
{
Some(self.config.unresolved_mark)
}
_ => Some(mark),
@ -1032,6 +1038,7 @@ impl<'a> VisitMut for Resolver<'a> {
fn visit_mut_module(&mut self, module: &mut Module) {
self.strict_mode = true;
self.is_module = true;
module.visit_mut_children_with(self)
}

View File

@ -2,4 +2,4 @@ var NaN__2 = 1;
{
let NaN__3 = 1;
console.log(NaN__3);
}console.log(NaN);
}console.log(NaN__2);

View File

@ -1,2 +1,2 @@
var NaN__2;
console.log(NaN.toString());
console.log(NaN__2.toString());

View File

@ -1,2 +1,2 @@
var NaN__2 = 5;
console.log(NaN.toString());
console.log(NaN__2.toString());

View File

@ -4570,7 +4570,7 @@ var load228 = __swcpack_require__.bind(void 0, function(module, exports) {
var Math1 = global.Math;
var RangeError1 = global.RangeError;
// eslint-disable-next-line no-shadow-restricted-names
global.Infinity;
var Infinity1 = global.Infinity;
var BaseBuffer = $ArrayBuffer;
var abs = Math1.abs;
var pow = Math1.pow;
@ -4595,7 +4595,7 @@ var load228 = __swcpack_require__.bind(void 0, function(module, exports) {
var e, m, c;
value = abs(value);
// eslint-disable-next-line no-self-compare
if (value != value || value === Infinity) {
if (value != value || value === Infinity1) {
// eslint-disable-next-line no-self-compare
m = value != value ? 1 : 0;
e = eMax;
@ -4645,7 +4645,7 @@ var load228 = __swcpack_require__.bind(void 0, function(module, exports) {
nBits += mLen;
for(; nBits > 0; m = m * 256 + buffer[i], i--, nBits -= 8);
if (e === 0) e = 1 - eBias;
else if (e === eMax) return m ? NaN : s ? -Infinity : Infinity;
else if (e === eMax) return m ? NaN : s ? -Infinity1 : Infinity1;
else {
m = m + pow(2, mLen);
e = e - eBias;