Skip to content

Commit

Permalink
js: avoid NaN and Infinity names inside with
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Oct 18, 2023
1 parent f9b4551 commit 427ee60
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 3 deletions.
46 changes: 46 additions & 0 deletions internal/bundler_tests/bundler_ts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2890,3 +2890,49 @@ func TestTSExperimentalDecoratorsManglePropsStaticMethods(t *testing.T) {
},
})
}

func TestTSPrintNonFiniteNumberInsideWith(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
// Use const enums to force inline values
const enum Foo {
NAN = 0 / 0,
POS_INF = 1 / 0,
NEG_INF = -1 / 0,
}
//! It's ok to use "NaN" and "Infinity" here
console.log(
Foo.NAN,
Foo.POS_INF,
Foo.NEG_INF,
)
checkPrecedence(
1 / Foo.NAN,
1 / Foo.POS_INF,
1 / Foo.NEG_INF,
)
//! We must not use "NaN" or "Infinity" inside "with"
with (x) {
console.log(
Foo.NAN,
Foo.POS_INF,
Foo.NEG_INF,
)
checkPrecedence(
1 / Foo.NAN,
1 / Foo.POS_INF,
1 / Foo.NEG_INF,
)
}
`,
},
entryPaths: []string{"/entry.ts"},
options: config.Options{
Mode: config.ModePassThrough,
AbsOutputFile: "/out.js",
},
})
}
34 changes: 34 additions & 0 deletions internal/bundler_tests/snapshots/snapshots_ts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1753,6 +1753,40 @@ console.log("success");
// Users/user/project/node_modules/package2/path.js
console.log("success");

================================================================================
TestTSPrintNonFiniteNumberInsideWith
---------- /out.js ----------
var Foo = /* @__PURE__ */ ((Foo2) => {
Foo2[Foo2["NAN"] = NaN] = "NAN";
Foo2[Foo2["POS_INF"] = Infinity] = "POS_INF";
Foo2[Foo2["NEG_INF"] = -Infinity] = "NEG_INF";
return Foo2;
})(Foo || {});
//! It's ok to use "NaN" and "Infinity" here
console.log(
NaN /* NAN */,
Infinity /* POS_INF */,
-Infinity /* NEG_INF */
);
checkPrecedence(
1 / NaN /* NAN */,
1 / Infinity /* POS_INF */,
1 / -Infinity /* NEG_INF */
);
//! We must not use "NaN" or "Infinity" inside "with"
with (x) {
console.log(
0 / 0 /* NAN */,
1 / 0 /* POS_INF */,
-1 / 0 /* NEG_INF */
);
checkPrecedence(
1 / (0 / 0) /* NAN */,
1 / (1 / 0) /* POS_INF */,
1 / (-1 / 0) /* NEG_INF */
);
}

================================================================================
TestTSSiblingEnum
---------- /out/number.js ----------
Expand Down
26 changes: 23 additions & 3 deletions internal/js_printer/js_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ type printer struct {
arrowExprStart int
forOfInitStart int

withNesting int
prevOpEnd int
needSpaceBeforeDot int
prevRegExpEnd int
Expand Down Expand Up @@ -549,9 +550,26 @@ func (p *printer) printNumber(value float64, level js_ast.L) {

if value != value {
p.printSpaceBeforeIdentifier()
p.print("NaN")
if p.withNesting != 0 {
// "with (x) NaN" really means "x.NaN" so avoid identifiers when "with" is present
wrap := level >= js_ast.LMultiply
if wrap {
p.print("(")
}
if p.options.MinifyWhitespace {
p.print("0/0")
} else {
p.print("0 / 0")
}
if wrap {
p.print(")")
}
} else {
p.print("NaN")
}
} else if value == positiveInfinity || value == negativeInfinity {
wrap := (p.options.MinifySyntax && level >= js_ast.LMultiply) ||
// "with (x) Infinity" really means "x.Infinity" so avoid identifiers when "with" is present
wrap := ((p.options.MinifySyntax || p.withNesting != 0) && level >= js_ast.LMultiply) ||
(value == negativeInfinity && level >= js_ast.LPrefix)
if wrap {
p.print("(")
Expand All @@ -562,7 +580,7 @@ func (p *printer) printNumber(value float64, level js_ast.L) {
} else {
p.printSpaceBeforeIdentifier()
}
if !p.options.MinifySyntax {
if !p.options.MinifySyntax && p.withNesting == 0 {
p.print("Infinity")
} else if p.options.MinifyWhitespace {
p.print("1/0")
Expand Down Expand Up @@ -4417,7 +4435,9 @@ func (p *printer) printStmt(stmt js_ast.Stmt, flags printStmtFlags) {
p.printExpr(s.Value, js_ast.LLowest, 0)
}
p.print(")")
p.withNesting++
p.printBody(s.Body)
p.withNesting--

case *js_ast.SLabel:
// Avoid printing a source mapping that masks the one from the label
Expand Down

0 comments on commit 427ee60

Please sign in to comment.