Skip to content

Commit

Permalink
Merge branch 'master' into fix/switch-4930
Browse files Browse the repository at this point in the history
  • Loading branch information
TrickyPi committed Apr 16, 2023
2 parents ca9d6b3 + ab33645 commit d25e759
Show file tree
Hide file tree
Showing 26 changed files with 187 additions and 154 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,23 @@
# rollup changelog

## 3.20.3

_2023-04-16_

### Bug Fixes

- Reduce memory consumption for function call parameter analysis (#4938)
- Fix types for `shouldTransformCachedModule` (#4932)

### Pull Requests

- [#4925](https://github.com/rollup/rollup/pull/4925): chore: repl style add scoped (@btea)
- [#4926](https://github.com/rollup/rollup/pull/4926): docs: Update the x_google_ignorelist url (@jecfish)
- [#4932](https://github.com/rollup/rollup/pull/4932): Allow shouldTransformCachedModule to return null (@bluwy)
- [#4935](https://github.com/rollup/rollup/pull/4935): Bump peter-evans/create-or-update-comment from 2 to 3 (@dependabot[bot])
- [#4936](https://github.com/rollup/rollup/pull/4936): Disable puppeteer sandbox to fix Vercel deployment (@lukastaegert)
- [#4938](https://github.com/rollup/rollup/pull/4938): Improve memory usage for parameter deoptimizations (@lukastaegert)

## 3.20.2

_2023-03-24_
Expand Down
2 changes: 1 addition & 1 deletion browser/package.json
@@ -1,6 +1,6 @@
{
"name": "@rollup/browser",
"version": "3.20.2",
"version": "3.20.3",
"description": "Next-generation ES module bundler browser build",
"main": "dist/rollup.browser.js",
"module": "dist/es/rollup.browser.js",
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "rollup",
"version": "3.20.2",
"version": "3.20.3",
"description": "Next-generation ES module bundler",
"main": "dist/rollup.js",
"module": "dist/es/rollup.js",
Expand Down
30 changes: 11 additions & 19 deletions src/ast/NodeInteractions.ts
Expand Up @@ -6,53 +6,45 @@ export const INTERACTION_ACCESSED = 0;
export const INTERACTION_ASSIGNED = 1;
export const INTERACTION_CALLED = 2;

// The first argument is the "this" context
export interface NodeInteractionAccessed {
args: null;
thisArg: ExpressionEntity | null;
args: readonly [ExpressionEntity | null];
type: typeof INTERACTION_ACCESSED;
}

export const NODE_INTERACTION_UNKNOWN_ACCESS: NodeInteractionAccessed = {
args: null,
thisArg: null,
args: [null],
type: INTERACTION_ACCESSED
};

// The first argument is the "this" context, the second argument the assigned expression
export interface NodeInteractionAssigned {
args: readonly [ExpressionEntity];
thisArg: ExpressionEntity | null;
args: readonly [ExpressionEntity | null, ExpressionEntity];
type: typeof INTERACTION_ASSIGNED;
}

export const UNKNOWN_ARG = [UNKNOWN_EXPRESSION] as const;

export const NODE_INTERACTION_UNKNOWN_ASSIGNMENT: NodeInteractionAssigned = {
args: UNKNOWN_ARG,
thisArg: null,
args: [null, UNKNOWN_EXPRESSION],
type: INTERACTION_ASSIGNED
};

// The first argument is the "this" context, the other arguments are the actual arguments
export interface NodeInteractionCalled {
args: readonly (ExpressionEntity | SpreadElement)[];
thisArg: ExpressionEntity | null;
args: readonly [ExpressionEntity | null, ...(ExpressionEntity | SpreadElement)[]];
type: typeof INTERACTION_CALLED;
withNew: boolean;
}

export const NO_ARGS = [];

// While this is technically a call without arguments, we can compare against
// this reference in places where precise values or thisArg would make a
// this reference in places where precise values or this argument would make a
// difference
export const NODE_INTERACTION_UNKNOWN_CALL: NodeInteractionCalled = {
args: NO_ARGS,
thisArg: null,
args: [null],
type: INTERACTION_CALLED,
withNew: false
};

// For tracking, called and assigned are uniquely determined by their .args
// while accessed is determined by .thisArg
// For tracking, interactions are uniquely determined by their .args
export type NodeInteraction =
| NodeInteractionAccessed
| NodeInteractionAssigned
Expand Down
5 changes: 3 additions & 2 deletions src/ast/nodes/CallExpression.ts
Expand Up @@ -41,11 +41,12 @@ export default class CallExpression
}
}
this.interaction = {
args: this.arguments,
thisArg:
args: [
this.callee instanceof MemberExpression && !this.callee.variable
? this.callee.object
: null,
...this.arguments
],
type: INTERACTION_CALLED,
withNew: false
};
Expand Down
6 changes: 4 additions & 2 deletions src/ast/nodes/ConditionalExpression.ts
@@ -1,5 +1,5 @@
import type MagicString from 'magic-string';
import { BLANK } from '../../utils/blank';
import { BLANK, EMPTY_ARRAY } from '../../utils/blank';
import type { NodeRenderOptions, RenderOptions } from '../../utils/renderHelpers';
import {
findFirstOccurrenceOutsideComment,
Expand Down Expand Up @@ -44,7 +44,9 @@ export default class ConditionalExpression extends NodeBase implements Deoptimiz
const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent;
this.usedBranch = null;
unusedBranch.deoptimizePath(UNKNOWN_PATH);
for (const expression of this.expressionsToBeDeoptimized) {
const { expressionsToBeDeoptimized } = this;
this.expressionsToBeDeoptimized = EMPTY_ARRAY as unknown as DeoptimizableEntity[];
for (const expression of expressionsToBeDeoptimized) {
expression.deoptimizeCache();
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/ast/nodes/LogicalExpression.ts
@@ -1,5 +1,5 @@
import type MagicString from 'magic-string';
import { BLANK } from '../../utils/blank';
import { BLANK, EMPTY_ARRAY } from '../../utils/blank';
import {
findFirstOccurrenceOutsideComment,
findNonWhiteSpace,
Expand Down Expand Up @@ -54,12 +54,14 @@ export default class LogicalExpression extends NodeBase implements Deoptimizable
const unusedBranch = this.usedBranch === this.left ? this.right : this.left;
this.usedBranch = null;
unusedBranch.deoptimizePath(UNKNOWN_PATH);
for (const expression of this.expressionsToBeDeoptimized) {
const { context, expressionsToBeDeoptimized } = this;
this.expressionsToBeDeoptimized = EMPTY_ARRAY as unknown as DeoptimizableEntity[];
for (const expression of expressionsToBeDeoptimized) {
expression.deoptimizeCache();
}
// Request another pass because we need to ensure "include" runs again if
// it is rendered
this.context.requestTreeshakingPass();
context.requestTreeshakingPass();
}
}

Expand Down
25 changes: 12 additions & 13 deletions src/ast/nodes/MemberExpression.ts
@@ -1,7 +1,7 @@
import type MagicString from 'magic-string';
import type { AstContext } from '../../Module';
import type { NormalizedTreeshakingOptions } from '../../rollup/types';
import { BLANK } from '../../utils/blank';
import { BLANK, EMPTY_ARRAY } from '../../utils/blank';
import { errorIllegalImportReassignment, errorMissingExport } from '../../utils/error';
import type { NodeRenderOptions, RenderOptions } from '../../utils/renderHelpers';
import type { DeoptimizableEntity } from '../DeoptimizableEntity';
Expand Down Expand Up @@ -101,8 +101,8 @@ export default class MemberExpression
declare propertyKey: ObjectPathKey | null;
declare type: NodeType.tMemberExpression;
variable: Variable | null = null;
protected declare assignmentInteraction: NodeInteractionAssigned & { thisArg: ExpressionEntity };
private declare accessInteraction: NodeInteractionAccessed & { thisArg: ExpressionEntity };
protected declare assignmentInteraction: NodeInteractionAssigned;
private declare accessInteraction: NodeInteractionAccessed;
private assignmentDeoptimized = false;
private bound = false;
private expressionsToBeDeoptimized: DeoptimizableEntity[] = [];
Expand Down Expand Up @@ -152,10 +152,10 @@ export default class MemberExpression
}

deoptimizeCache(): void {
const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized;
this.expressionsToBeDeoptimized = [];
const { expressionsToBeDeoptimized, object } = this;
this.expressionsToBeDeoptimized = EMPTY_ARRAY as unknown as DeoptimizableEntity[];
this.propertyKey = UnknownKey;
this.object.deoptimizePath(UNKNOWN_PATH);
object.deoptimizePath(UNKNOWN_PATH);
for (const expression of expressionsToBeDeoptimized) {
expression.deoptimizeCache();
}
Expand Down Expand Up @@ -185,8 +185,8 @@ export default class MemberExpression
if (this.isUndefined) {
return undefined;
}
this.expressionsToBeDeoptimized.push(origin);
if (path.length < MAX_PATH_DEPTH) {
if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
this.expressionsToBeDeoptimized.push(origin);
return this.object.getLiteralValueAtPath(
[this.getPropertyKey(), ...path],
recursionTracker,
Expand All @@ -213,8 +213,8 @@ export default class MemberExpression
if (this.isUndefined) {
return [UNDEFINED_EXPRESSION, false];
}
this.expressionsToBeDeoptimized.push(origin);
if (path.length < MAX_PATH_DEPTH) {
if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
this.expressionsToBeDeoptimized.push(origin);
return this.object.getReturnExpressionWhenCalledAtPath(
[this.getPropertyKey(), ...path],
interaction,
Expand Down Expand Up @@ -297,7 +297,7 @@ export default class MemberExpression

initialise(): void {
this.propertyKey = getResolvablePropertyKey(this);
this.accessInteraction = { args: null, thisArg: this.object, type: INTERACTION_ACCESSED };
this.accessInteraction = { args: [this.object], type: INTERACTION_ACCESSED };
}

isSkippedAsOptional(origin: DeoptimizableEntity): boolean {
Expand Down Expand Up @@ -340,8 +340,7 @@ export default class MemberExpression

setAssignedValue(value: ExpressionEntity) {
this.assignmentInteraction = {
args: [value],
thisArg: this.object,
args: [this.object, value],
type: INTERACTION_ASSIGNED
};
}
Expand Down
3 changes: 1 addition & 2 deletions src/ast/nodes/NewExpression.ts
Expand Up @@ -53,8 +53,7 @@ export default class NewExpression extends NodeBase {

initialise(): void {
this.interaction = {
args: this.arguments,
thisArg: null,
args: [null, ...this.arguments],
type: INTERACTION_CALLED,
withNew: true
};
Expand Down
10 changes: 7 additions & 3 deletions src/ast/nodes/TaggedTemplateExpression.ts
Expand Up @@ -18,6 +18,7 @@ export default class TaggedTemplateExpression extends CallExpressionBase {
declare quasi: TemplateLiteral;
declare tag: ExpressionNode;
declare type: NodeType.tTaggedTemplateExpression;
private declare args: ExpressionEntity[];

bind(): void {
super.bind();
Expand Down Expand Up @@ -54,17 +55,20 @@ export default class TaggedTemplateExpression extends CallExpressionBase {
this.tag.include(context, includeChildrenRecursively);
this.quasi.include(context, includeChildrenRecursively);
}
this.tag.includeCallArguments(context, this.interaction.args);
this.tag.includeCallArguments(context, this.args);
const [returnExpression] = this.getReturnExpression();
if (!returnExpression.included) {
returnExpression.include(context, false);
}
}

initialise(): void {
this.args = [UNKNOWN_EXPRESSION, ...this.quasi.expressions];
this.interaction = {
args: [UNKNOWN_EXPRESSION, ...this.quasi.expressions],
thisArg: this.tag instanceof MemberExpression && !this.tag.variable ? this.tag.object : null,
args: [
this.tag instanceof MemberExpression && !this.tag.variable ? this.tag.object : null,
...this.args
],
type: INTERACTION_CALLED,
withNew: false
};
Expand Down
7 changes: 1 addition & 6 deletions src/ast/nodes/ThisExpression.ts
Expand Up @@ -23,12 +23,7 @@ export default class ThisExpression extends NodeBase {
path: ObjectPath,
recursionTracker: PathTracker
): void {
// We rewrite the parameter so that a ThisVariable can detect self-mutations
this.variable.deoptimizeArgumentsOnInteractionAtPath(
interaction.thisArg === this ? { ...interaction, thisArg: this.variable } : interaction,
path,
recursionTracker
);
this.variable.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
}

deoptimizePath(path: ObjectPath): void {
Expand Down
34 changes: 17 additions & 17 deletions src/ast/nodes/shared/CallExpressionBase.ts
@@ -1,3 +1,4 @@
import { EMPTY_ARRAY, EMPTY_SET } from '../../../utils/blank';
import type { DeoptimizableEntity } from '../../DeoptimizableEntity';
import type { HasEffectsContext } from '../../ExecutionContext';
import type { NodeInteraction, NodeInteractionCalled } from '../../NodeInteractions';
Expand All @@ -15,36 +16,32 @@ import { NodeBase } from './Node';
export default abstract class CallExpressionBase extends NodeBase implements DeoptimizableEntity {
protected declare interaction: NodeInteractionCalled;
protected returnExpression: [expression: ExpressionEntity, isPure: boolean] | null = null;
private readonly deoptimizableDependentExpressions: DeoptimizableEntity[] = [];
private readonly expressionsToBeDeoptimized = new Set<ExpressionEntity>();
private deoptimizableDependentExpressions: DeoptimizableEntity[] = [];
private expressionsToBeDeoptimized = new Set<ExpressionEntity>();

deoptimizeArgumentsOnInteractionAtPath(
interaction: NodeInteraction,
path: ObjectPath,
recursionTracker: PathTracker
): void {
const { args, thisArg } = interaction;
const { args } = interaction;
const [returnExpression, isPure] = this.getReturnExpression(recursionTracker);
if (isPure) return;
const deoptimizedExpressions = args.filter(
expression => !!expression && expression !== UNKNOWN_EXPRESSION
) as ExpressionEntity[];
if (deoptimizedExpressions.length === 0) return;
if (returnExpression === UNKNOWN_EXPRESSION) {
thisArg?.deoptimizePath(UNKNOWN_PATH);
if (args) {
for (const argument of args) {
argument.deoptimizePath(UNKNOWN_PATH);
}
for (const expression of deoptimizedExpressions) {
expression.deoptimizePath(UNKNOWN_PATH);
}
} else {
recursionTracker.withTrackedEntityAtPath(
path,
returnExpression,
() => {
if (thisArg) {
this.expressionsToBeDeoptimized.add(thisArg);
}
if (args) {
for (const argument of args) {
this.expressionsToBeDeoptimized.add(argument);
}
for (const expression of deoptimizedExpressions) {
this.expressionsToBeDeoptimized.add(expression);
}
returnExpression.deoptimizeArgumentsOnInteractionAtPath(
interaction,
Expand All @@ -60,10 +57,13 @@ export default abstract class CallExpressionBase extends NodeBase implements Deo
deoptimizeCache(): void {
if (this.returnExpression?.[0] !== UNKNOWN_EXPRESSION) {
this.returnExpression = UNKNOWN_RETURN_EXPRESSION;
for (const expression of this.deoptimizableDependentExpressions) {
const { deoptimizableDependentExpressions, expressionsToBeDeoptimized } = this;
this.expressionsToBeDeoptimized = EMPTY_SET;
this.deoptimizableDependentExpressions = EMPTY_ARRAY as unknown as DeoptimizableEntity[];
for (const expression of deoptimizableDependentExpressions) {
expression.deoptimizeCache();
}
for (const expression of this.expressionsToBeDeoptimized) {
for (const expression of expressionsToBeDeoptimized) {
expression.deoptimizePath(UNKNOWN_PATH);
}
}
Expand Down
7 changes: 2 additions & 5 deletions src/ast/nodes/shared/Expression.ts
Expand Up @@ -99,10 +99,7 @@ export const UNKNOWN_RETURN_EXPRESSION: [expression: ExpressionEntity, isPure: b
];

export const deoptimizeInteraction = (interaction: NodeInteraction) => {
interaction.thisArg?.deoptimizePath(UNKNOWN_PATH);
if (interaction.args) {
for (const argument of interaction.args) {
argument.deoptimizePath(UNKNOWN_PATH);
}
for (const argument of interaction.args) {
argument?.deoptimizePath(UNKNOWN_PATH);
}
};

0 comments on commit d25e759

Please sign in to comment.