Skip to content

Commit

Permalink
Track Access to Properties
Browse files Browse the repository at this point in the history
  • Loading branch information
TrickyPi committed Mar 6, 2024
1 parent f44dac3 commit c8a0fc6
Show file tree
Hide file tree
Showing 14 changed files with 99 additions and 4 deletions.
15 changes: 12 additions & 3 deletions src/ast/nodes/ImportExpression.ts
Expand Up @@ -42,6 +42,7 @@ export default class ImportExpression extends NodeBase {
declare type: NodeType.tImportExpression;
declare sourceAstNode: AstNode;

private accessedPropKey = new Set<string>();
private attributes: string | null | true = null;
private mechanism: DynamicImportMechanism | null = null;
private namespaceExportName: string | false | undefined = undefined;
Expand Down Expand Up @@ -82,9 +83,13 @@ export default class ImportExpression extends NodeBase {
// Case 1: const { foo } = await import('bar')
if (parent2 instanceof VariableDeclarator) {
const declaration = parent2.id;
return declaration instanceof ObjectPattern
? getDeterministicObjectDestructure(declaration)
: undefined;
if (declaration instanceof Identifier) {
return this.accessedPropKey.size > 0 ? [...this.accessedPropKey] : undefined;
}
if (declaration instanceof ObjectPattern) {
return getDeterministicObjectDestructure(declaration);
}
return undefined;
}

// Case 2: (await import('bar')).foo
Expand Down Expand Up @@ -147,6 +152,10 @@ export default class ImportExpression extends NodeBase {
}
}

addAccessedPropKey(key: string): void {
this.accessedPropKey.add(key);
}

hasEffects(): boolean {
return true;
}
Expand Down
17 changes: 17 additions & 0 deletions src/ast/nodes/MemberExpression.ts
Expand Up @@ -27,9 +27,12 @@ import {
} from '../utils/PathTracker';
import { UNDEFINED_EXPRESSION } from '../values';
import ExternalVariable from '../variables/ExternalVariable';
import LocalVariable from '../variables/LocalVariable';
import type NamespaceVariable from '../variables/NamespaceVariable';
import type Variable from '../variables/Variable';
import AwaitExpression from './AwaitExpression';
import Identifier from './Identifier';
import type ImportExpression from './ImportExpression';
import Literal from './Literal';
import type * as NodeType from './NodeType';
import type PrivateIdentifier from './PrivateIdentifier';
Expand All @@ -46,6 +49,10 @@ import {
import type { ChainElement, ExpressionNode, IncludeChildren } from './shared/Node';
import { NodeBase } from './shared/Node';

function isImportExpression(node: ExpressionNode): node is ImportExpression {
return node.type === 'ImportExpression';
}

// To avoid infinite recursions
const MAX_PATH_DEPTH = 7;

Expand Down Expand Up @@ -161,6 +168,16 @@ export default class MemberExpression
} else {
super.bind();
}
if (baseVariable instanceof LocalVariable) {
const init = baseVariable.init;
if (
init instanceof AwaitExpression &&
isImportExpression(init.argument) &&
typeof this.propertyKey === 'string'
) {
init.argument.addAccessedPropKey(this.propertyKey);
}
}
}

deoptimizeArgumentsOnInteractionAtPath(
Expand Down
6 changes: 5 additions & 1 deletion src/ast/variables/LocalVariable.ts
Expand Up @@ -28,6 +28,9 @@ import Variable from './Variable';

export default class LocalVariable extends Variable {
calledFromTryStatement = false;

init: ExpressionEntity;

readonly declarations: (Identifier | ExportDefaultDeclaration)[];
readonly module: Module;
readonly kind: VariableKind;
Expand All @@ -41,13 +44,14 @@ export default class LocalVariable extends Variable {
constructor(
name: string,
declarator: Identifier | ExportDefaultDeclaration | null,
private init: ExpressionEntity,
init: ExpressionEntity,
context: AstContext,
kind: VariableKind
) {
super(name);
this.declarations = declarator ? [declarator] : [];
this.deoptimizationTracker = context.deoptimizationTracker;
this.init = init;
this.module = context.module;
this.kind = kind;
}
Expand Down
@@ -0,0 +1,3 @@
module.exports = defineTest({
description: 'tree-shakes dynamic imports with identifier'
});
@@ -0,0 +1,7 @@
define(['exports'], (function (exports) { 'use strict';

const foo = () => {};

exports.foo = foo;

}));
@@ -0,0 +1,8 @@
define(['require'], (function (require) { 'use strict';

(async () => {
const module = await new Promise(function (resolve, reject) { require(['./generated-module'], resolve, reject); });
module.foo();
})();

}));
@@ -0,0 +1,5 @@
'use strict';

const foo = () => {};

exports.foo = foo;
@@ -0,0 +1,6 @@
'use strict';

(async () => {
const module = await Promise.resolve().then(function () { return require('./generated-module.js'); });
module.foo();
})();
@@ -0,0 +1,3 @@
const foo = () => {};

export { foo };
@@ -0,0 +1,4 @@
(async () => {
const module = await import('./generated-module.js');
module.foo();
})();
@@ -0,0 +1,10 @@
System.register([], (function (exports) {
'use strict';
return {
execute: (function () {

const foo = exports("foo", () => {});

})
};
}));
@@ -0,0 +1,13 @@
System.register([], (function (exports, module) {
'use strict';
return {
execute: (function () {

(async () => {
const module$1 = await module.import('./generated-module.js');
module$1.foo();
})();

})
};
}));
4 changes: 4 additions & 0 deletions test/chunking-form/samples/dynamic-import-identifier/main.js
@@ -0,0 +1,4 @@
(async () => {
const module = await import('./module');
module.foo();
})();
@@ -0,0 +1,2 @@
export const foo = () => {};
export const bar = () => {};

0 comments on commit c8a0fc6

Please sign in to comment.