Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(shaker): partial support for ts compiled code (fixes #820) #836

Merged
merged 1 commit into from Sep 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -65,18 +65,6 @@ color.green = '#0f0';
exports.__linariaPreval = [color];"
`;

exports[`keeps only the last assignment of each exported variable 1`] = `
"\\"use strict\\";

var bar = function bar() {
return 'hello world';
};

exports.bar = bar;
var foo = exports.bar();
exports.__linariaPreval = [foo];"
`;

exports[`keeps reused exports 1`] = `
"\\"use strict\\";

Expand Down
16 changes: 0 additions & 16 deletions packages/babel/__tests__/evaluators/shaker.test.ts
Expand Up @@ -241,19 +241,3 @@ it('keeps reused exports', () => {

expect(shaken).toMatchSnapshot();
});

it('keeps only the last assignment of each exported variable', () => {
const [shaken] = _shake()`
const bar = function() {
return 'hello world';
};

exports.bar = "bar";
exports.bar = bar;

const foo = exports.bar();
exports.__linariaPreval = [foo];
`;

expect(shaken).toMatchSnapshot();
});
6 changes: 6 additions & 0 deletions packages/shaker/src/DepsGraph.ts
Expand Up @@ -77,6 +77,12 @@ export default class DepsGraph {
}

addExport(name: string, node: t.Node) {
const existed = this.exports.get(name);
if (existed) {
// Sometimes export can be defined more than once and in that case we have to keep all export statements
this.addEdge(node, existed);
}

this.exports.set(name, node);
}

Expand Down
43 changes: 30 additions & 13 deletions packages/shaker/src/graphBuilder.ts
Expand Up @@ -22,21 +22,23 @@ class GraphBuilder extends GraphBuilderState {
}

private isExportsIdentifier(node: Node) {
if (
t.isIdentifier(node) &&
this.scope.getDeclaration(node) === ScopeManager.globalExportsIdentifier
) {
return true;
if (t.isIdentifier(node)) {
return (
this.scope.getDeclaration(node) === ScopeManager.globalExportsIdentifier
);
}

return (
t.isMemberExpression(node) &&
t.isIdentifier(node.property) &&
node.property.name === 'exports' &&
t.isIdentifier(node.object) &&
this.scope.getDeclaration(node.object) ===
ScopeManager.globalModuleIdentifier
);
if (t.isMemberExpression(node)) {
return (
t.isIdentifier(node.property) &&
node.property.name === 'exports' &&
t.isIdentifier(node.object) &&
this.scope.getDeclaration(node.object) ===
ScopeManager.globalModuleIdentifier
);
}

return false;
}

private isExportsAssigment(node: Node): node is AssignmentExpression {
Expand All @@ -59,6 +61,17 @@ class GraphBuilder extends GraphBuilderState {
return false;
}

private isTSExporterCall(
node: Node
): node is t.CallExpression & { arguments: [t.StringLiteral, t.Identifier] } {
if (!t.isCallExpression(node) || node.arguments.length !== 2) {
return false;
}

// FIXME: more precisely check
return !(!t.isIdentifier(node.callee) || node.callee.name !== 'exporter');
}

/*
* Implements a default behaviour for AST-nodes:
* • visits every child;
Expand Down Expand Up @@ -158,6 +171,10 @@ class GraphBuilder extends GraphBuilderState {
);
}
}
} else if (this.isTSExporterCall(node)) {
const [name, identifier] = node.arguments;
this.graph.addExport(name.value, node);
this.graph.addEdge(node, identifier);
}

const isScopable = t.isScopable(node);
Expand Down
65 changes: 65 additions & 0 deletions packages/shaker/src/langs/core.ts
Expand Up @@ -3,6 +3,7 @@ import type {
AssignmentExpression,
Block,
CallExpression,
CatchClause,
Directive,
ExpressionStatement,
ForInStatement,
Expand Down Expand Up @@ -75,6 +76,48 @@ function getCallee(node: CallExpression): Node {
return node.callee;
}

function isTSLib(node: t.Node, scope: ScopeManager) {
if (!t.isIdentifier(node)) {
return false;
}

const declaration = scope.getDeclaration(node);
return t.isIdentifier(declaration) && declaration.name === 'tslib_1';
}

function isTSReexport(
node: t.Node,
scope: ScopeManager
): node is t.Node & { callee: { object: t.Identifier } } {
if (!t.isCallExpression(node)) {
return false;
}

const {
callee,
arguments: [, exportsIdentifier],
} = node;
if (
!t.isIdentifier(exportsIdentifier) ||
exportsIdentifier.name !== 'exports' ||
scope.getDeclaration(exportsIdentifier) !==
ScopeManager.globalExportsIdentifier
) {
return false;
}

if (!t.isMemberExpression(callee)) {
return false;
}

const { object, property } = callee;
if (!t.isIdentifier(property) || property.name !== '__exportStar') {
return false;
}

return isTSLib(object, scope);
}

function findWildcardReexportStatement(
node: t.CallExpression,
identifierName: string,
Expand Down Expand Up @@ -197,6 +240,10 @@ export const visitors: Visitors = {
// keep function name in expressions like `const a = function a();`
this.graph.addEdge(node, node.id);
}

if (t.isFunctionDeclaration(node) && node.id) {
this.graph.addEdge(node, node.id);
}
},

/*
Expand Down Expand Up @@ -258,6 +305,12 @@ export const visitors: Visitors = {
});
},

CatchClause(this: GraphBuilderState, node: CatchClause) {
this.baseVisit(node);

this.graph.addEdge(node, node.body);
},

IfStatement(this: GraphBuilderState, node: IfStatement) {
this.baseVisit(node);
this.graph.addEdge(node, node.consequent);
Expand Down Expand Up @@ -519,6 +572,18 @@ export const visitors: Visitors = {
[Identifier, Identifier | null]
>;
if (!declared) {
// Is it a ts reexport?
// tslib_1.__exportStar(require("./Async"), exports);
if (parent && isTSReexport(parent, this.scope)) {
if (!this.graph.imports.has(source)) {
this.graph.imports.set(source, []);
}

this.graph.addEdge(parent.callee.object, parent);
this.graph.reexports.push(parent.callee.object);
this.graph.importTypes.set(source, 'reexport');
}

// This is a standalone `require`
return;
}
Expand Down
4 changes: 3 additions & 1 deletion packages/shaker/src/scope.ts
Expand Up @@ -56,6 +56,8 @@ const getId = (scope: Scope, identifier: t.Identifier | string): string => {
}`;
};

const globalIdentifiers = new Set(['exports', 'module']);

export default class ScopeManager {
public static globalExportsIdentifier = t.identifier('exports');
public static globalModuleIdentifier = t.identifier('module');
Expand Down Expand Up @@ -125,7 +127,7 @@ export default class ScopeManager {
const scope = this.stack
.slice(stack)
.find((s) => !isHoistable || functionScopes.has(s))!;
if (this.global.has(idName)) {
if (this.global.has(idName) && !globalIdentifiers.has(idName)) {
// It's probably a declaration of a previous referenced identifier
// Let's use naïve implementation of hoisting
const promise = this.declarations.get(
Expand Down