From bbce2b7d578b1a0c24511bb2f85d0e143e621785 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Fri, 21 Apr 2023 06:28:58 +0200 Subject: [PATCH 1/3] Deoptimize right side in for-of loops (#4949) --- src/ast/nodes/ForOfStatement.ts | 3 ++- test/function/samples/deoptimize-loop-element/_config.js | 3 +++ test/function/samples/deoptimize-loop-element/main.js | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 test/function/samples/deoptimize-loop-element/_config.js create mode 100644 test/function/samples/deoptimize-loop-element/main.js diff --git a/src/ast/nodes/ForOfStatement.ts b/src/ast/nodes/ForOfStatement.ts index b3e9e63244b..ea4f40795c1 100644 --- a/src/ast/nodes/ForOfStatement.ts +++ b/src/ast/nodes/ForOfStatement.ts @@ -3,7 +3,7 @@ import { NO_SEMICOLON, type RenderOptions } from '../../utils/renderHelpers'; import type { InclusionContext } from '../ExecutionContext'; import BlockScope from '../scopes/BlockScope'; import type Scope from '../scopes/Scope'; -import { EMPTY_PATH } from '../utils/PathTracker'; +import { EMPTY_PATH, UNKNOWN_PATH } from '../utils/PathTracker'; import type MemberExpression from './MemberExpression'; import type * as NodeType from './NodeType'; import type VariableDeclaration from './VariableDeclaration'; @@ -60,6 +60,7 @@ export default class ForOfStatement extends StatementBase { protected applyDeoptimizations(): void { this.deoptimized = true; this.left.deoptimizePath(EMPTY_PATH); + this.right.deoptimizePath(UNKNOWN_PATH); this.context.requestTreeshakingPass(); } } diff --git a/test/function/samples/deoptimize-loop-element/_config.js b/test/function/samples/deoptimize-loop-element/_config.js new file mode 100644 index 00000000000..0e0cd6ac573 --- /dev/null +++ b/test/function/samples/deoptimize-loop-element/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'deoptimizes the loop element when it is reassigned' +}; diff --git a/test/function/samples/deoptimize-loop-element/main.js b/test/function/samples/deoptimize-loop-element/main.js new file mode 100644 index 00000000000..a5a0d0d5edb --- /dev/null +++ b/test/function/samples/deoptimize-loop-element/main.js @@ -0,0 +1,7 @@ +const foo = [{ value: 1 }]; + +for (const item of foo) { + item.value = 0; +} + +assert.ok(foo[0].value === 0 ? true : false); From 2820962446b40b7dfab9bdd936be1e230d8b944c Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Fri, 21 Apr 2023 06:29:22 +0200 Subject: [PATCH 2/3] Support default exported classes that extend other classes (#4950) --- src/ast/nodes/ExportDefaultDeclaration.ts | 37 ++++++------------- .../_config.js | 3 ++ .../_expected.js | 7 ++++ .../main.js | 5 +++ 4 files changed, 27 insertions(+), 25 deletions(-) create mode 100644 test/form/samples/default-export-anonymous-class-extends/_config.js create mode 100644 test/form/samples/default-export-anonymous-class-extends/_expected.js create mode 100644 test/form/samples/default-export-anonymous-class-extends/main.js diff --git a/src/ast/nodes/ExportDefaultDeclaration.ts b/src/ast/nodes/ExportDefaultDeclaration.ts index ca9372bd5c6..7a626667691 100644 --- a/src/ast/nodes/ExportDefaultDeclaration.ts +++ b/src/ast/nodes/ExportDefaultDeclaration.ts @@ -21,18 +21,10 @@ function getDeclarationStart(code: string, start: number): number { return findNonWhiteSpace(code, findFirstOccurrenceOutsideComment(code, 'default', start) + 7); } -function getIdInsertPosition( - code: string, - declarationKeyword: string, - endMarker: string, - start: number -): number { +function getFunctionIdInsertPosition(code: string, start: number): number { const declarationEnd = - findFirstOccurrenceOutsideComment(code, declarationKeyword, start) + declarationKeyword.length; - code = code.slice( - declarationEnd, - findFirstOccurrenceOutsideComment(code, endMarker, declarationEnd) - ); + findFirstOccurrenceOutsideComment(code, 'function', start) + 'function'.length; + code = code.slice(declarationEnd, findFirstOccurrenceOutsideComment(code, '(', declarationEnd)); const generatorStarPos = findFirstOccurrenceOutsideComment(code, '*'); if (generatorStarPos === -1) { return declarationEnd; @@ -76,18 +68,18 @@ export default class ExportDefaultDeclaration extends NodeBase { this.renderNamedDeclaration( code, declarationStart, - 'function', - '(', - this.declaration.id === null, + this.declaration.id === null + ? getFunctionIdInsertPosition(code.original, declarationStart) + : null, options ); } else if (this.declaration instanceof ClassDeclaration) { this.renderNamedDeclaration( code, declarationStart, - 'class', - '{', - this.declaration.id === null, + this.declaration.id === null + ? findFirstOccurrenceOutsideComment(code.original, 'class', start) + 'class'.length + : null, options ); } else if (this.variable.getOriginalVariable() !== this.variable) { @@ -114,9 +106,7 @@ export default class ExportDefaultDeclaration extends NodeBase { private renderNamedDeclaration( code: MagicString, declarationStart: number, - declarationKeyword: string, - endMarker: string, - needsId: boolean, + idInsertPosition: number | null, options: RenderOptions ): void { const { @@ -128,11 +118,8 @@ export default class ExportDefaultDeclaration extends NodeBase { // Remove `export default` code.remove(this.start, declarationStart); - if (needsId) { - code.appendLeft( - getIdInsertPosition(code.original, declarationKeyword, endMarker, declarationStart), - ` ${name}` - ); + if (idInsertPosition !== null) { + code.appendLeft(idInsertPosition, ` ${name}`); } if ( format === 'system' && diff --git a/test/form/samples/default-export-anonymous-class-extends/_config.js b/test/form/samples/default-export-anonymous-class-extends/_config.js new file mode 100644 index 00000000000..2ed4457e53c --- /dev/null +++ b/test/form/samples/default-export-anonymous-class-extends/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'handles default exported classes extending a regular expression argument (#4783)' +}; diff --git a/test/form/samples/default-export-anonymous-class-extends/_expected.js b/test/form/samples/default-export-anonymous-class-extends/_expected.js new file mode 100644 index 00000000000..f8f4d1e17a5 --- /dev/null +++ b/test/form/samples/default-export-anonymous-class-extends/_expected.js @@ -0,0 +1,7 @@ +function foo(val) { + return val; +} + +class main extends foo(/1/) {} + +export { main as default }; diff --git a/test/form/samples/default-export-anonymous-class-extends/main.js b/test/form/samples/default-export-anonymous-class-extends/main.js new file mode 100644 index 00000000000..87344a1ea57 --- /dev/null +++ b/test/form/samples/default-export-anonymous-class-extends/main.js @@ -0,0 +1,5 @@ +function foo(val) { + return val; +} + +export default class extends foo(/1/) {} From 5af8799c2cc695cc54710494c3378dcfc2eb7611 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Fri, 21 Apr 2023 06:35:20 +0200 Subject: [PATCH 3/3] 3.20.7 --- CHANGELOG.md | 15 +++++++++++++++ browser/package.json | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75e53f99494..94492ea9418 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # rollup changelog +## 3.20.7 + +_2023-04-21_ + +### Bug Fixes + +- Properly track array element mutations when iterating with a for-of loop (#4949) +- Handle default exporting an anonymous class that extends another class (#4950) + +### Pull Requests + +- [#4943](https://github.com/rollup/rollup/pull/4943): Add a test for reserved keywords used as import/export specifiers (@Andarist) +- [#4949](https://github.com/rollup/rollup/pull/4949): Deoptimize right side in for-of loops (@lukastaegert) +- [#4950](https://github.com/rollup/rollup/pull/4950): Support default exported classes that extend other classes (@lukastaegert) + ## 3.20.6 _2023-04-18_ diff --git a/browser/package.json b/browser/package.json index 13f1791055e..2e3b11f9d11 100644 --- a/browser/package.json +++ b/browser/package.json @@ -1,6 +1,6 @@ { "name": "@rollup/browser", - "version": "3.20.6", + "version": "3.20.7", "description": "Next-generation ES module bundler browser build", "main": "dist/rollup.browser.js", "module": "dist/es/rollup.browser.js", diff --git a/package-lock.json b/package-lock.json index e17746ed4c7..3c39d2ffc9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rollup", - "version": "3.20.6", + "version": "3.20.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "rollup", - "version": "3.20.6", + "version": "3.20.7", "license": "MIT", "bin": { "rollup": "dist/bin/rollup" diff --git a/package.json b/package.json index e0e3076704c..68c804a3760 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rollup", - "version": "3.20.6", + "version": "3.20.7", "description": "Next-generation ES module bundler", "main": "dist/rollup.js", "module": "dist/es/rollup.js",