Skip to content

Commit

Permalink
Refine SystemJS export rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Aug 2, 2021
1 parent 66d2d82 commit 52ce573
Show file tree
Hide file tree
Showing 42 changed files with 563 additions and 530 deletions.
9 changes: 1 addition & 8 deletions src/Chunk.ts
Expand Up @@ -5,7 +5,6 @@ import Module from './Module';
import ExportDefaultDeclaration from './ast/nodes/ExportDefaultDeclaration';
import FunctionDeclaration from './ast/nodes/FunctionDeclaration';
import ChildScope from './ast/scopes/ChildScope';
import { UNDEFINED_EXPRESSION } from './ast/values';
import ExportDefaultVariable from './ast/variables/ExportDefaultVariable';
import ExportShimVariable from './ast/variables/ExportShimVariable';
import LocalVariable from './ast/variables/LocalVariable';
Expand Down Expand Up @@ -83,7 +82,6 @@ export type ChunkExports = {
expression: string | null;
hoisted: boolean;
local: string;
uninitialized: boolean;
}[];

export interface ReexportSpecifier {
Expand Down Expand Up @@ -997,12 +995,8 @@ export default class Chunk {
}
let expression = null;
let hoisted = false;
let uninitialized = false;
let local = variable.getName();
if (variable instanceof LocalVariable) {
if (variable.init === UNDEFINED_EXPRESSION) {
uninitialized = true;
}
for (const declaration of variable.declarations) {
if (
declaration.parent instanceof FunctionDeclaration ||
Expand All @@ -1024,8 +1018,7 @@ export default class Chunk {
exported: exportName,
expression,
hoisted,
local,
uninitialized
local
});
}
return exports;
Expand Down
58 changes: 31 additions & 27 deletions src/ast/nodes/AssignmentExpression.ts
Expand Up @@ -7,10 +7,15 @@ import {
removeLineBreaks,
RenderOptions
} from '../../utils/renderHelpers';
import { getSystemExportFunctionLeft } from '../../utils/systemJsRendering';
import {
renderSystemExportExpression,
renderSystemExportFunction,
renderSystemExportSequenceAfterExpression
} from '../../utils/systemJsRendering';
import { createHasEffectsContext, HasEffectsContext, InclusionContext } from '../ExecutionContext';
import { EMPTY_PATH, ObjectPath, UNKNOWN_PATH } from '../utils/PathTracker';
import Variable from '../variables/Variable';
import Identifier from './Identifier';
import * as NodeType from './NodeType';
import { ExpressionNode, IncludeChildren, NodeBase } from './shared/Node';
import { PatternNode } from './shared/Pattern';
Expand Down Expand Up @@ -68,7 +73,7 @@ export default class AssignmentExpression extends NodeBase {
render(
code: MagicString,
options: RenderOptions,
{ preventASI, renderedParentType }: NodeRenderOptions = BLANK
{ preventASI, renderedParentType, renderedSurroundingElement }: NodeRenderOptions = BLANK
): void {
if (this.left.included) {
this.left.render(code, options);
Expand All @@ -83,40 +88,39 @@ export default class AssignmentExpression extends NodeBase {
removeLineBreaks(code, inclusionStart, this.right.start);
}
this.right.render(code, options, {
renderedParentType: renderedParentType || this.parent.type
renderedParentType: renderedParentType || renderedSurroundingElement || this.parent.type
});
}
if (options.format === 'system') {
const exportNames =
this.left.variable && options.exportNamesByVariable.get(this.left.variable);
if (this.left.type === 'Identifier' && exportNames) {
const _ = options.compact ? '' : ' ';
const operatorPos = findFirstOccurrenceOutsideComment(
code.original,
this.operator,
this.left.end
);
const operation =
this.operator.length > 1 ? `${exportNames[0]}${_}${this.operator.slice(0, -1)}${_}` : '';
code.overwrite(
operatorPos,
findNonWhiteSpace(code.original, operatorPos + this.operator.length),
`=${_}${
exportNames.length === 1
? `exports('${exportNames[0]}',${_}`
: getSystemExportFunctionLeft([this.left.variable!], false, options)
}${operation}`
);
code.appendLeft(this.right.end, ')');
if (this.left instanceof Identifier) {
const variable = this.left.variable!;
const exportNames = options.exportNamesByVariable.get(variable);
if (exportNames) {
if (exportNames.length === 1) {
renderSystemExportExpression(variable, this.start, this.end, code, options);
} else {
renderSystemExportSequenceAfterExpression(
variable,
this.start,
this.end,
this.parent.type !== NodeType.ExpressionStatement,
code,
options
);
}
}
} else {
const systemPatternExports: Variable[] = [];
this.left.addExportedVariables(systemPatternExports, options.exportNamesByVariable);
if (systemPatternExports.length > 0) {
code.prependRight(
renderSystemExportFunction(
systemPatternExports,
this.start,
`(${getSystemExportFunctionLeft(systemPatternExports, true, options)}`
this.end,
(renderedParentType || renderedSurroundingElement) === NodeType.ExpressionStatement,
code,
options
);
code.appendLeft(this.end, '))');
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/ast/nodes/ImportExpression.ts
Expand Up @@ -51,7 +51,8 @@ export default class ImportExpression extends NodeBase {
code.overwrite(
this.start,
this.end,
`Promise.resolve().then(function${_}()${_}{${_}return ${this.inlineNamespace.getName()}${s}${_}})`
`Promise.resolve().then(function${_}()${_}{${_}return ${this.inlineNamespace.getName()}${s}${_}})`,
{ contentOnly: true }
);
return;
}
Expand All @@ -60,9 +61,10 @@ export default class ImportExpression extends NodeBase {
code.overwrite(
this.start,
findFirstOccurrenceOutsideComment(code.original, '(', this.start + 6) + 1,
this.mechanism.left
this.mechanism.left,
{ contentOnly: true }
);
code.overwrite(this.end - 1, this.end, this.mechanism.right);
code.overwrite(this.end - 1, this.end, this.mechanism.right, { contentOnly: true });
}
this.source.render(code, options);
}
Expand Down
52 changes: 19 additions & 33 deletions src/ast/nodes/UpdateExpression.ts
@@ -1,8 +1,9 @@
import MagicString from 'magic-string';
import { RenderOptions } from '../../utils/renderHelpers';
import {
getSystemExportFunctionLeft,
getSystemExportStatement
renderSystemExportExpression,
renderSystemExportSequenceAfterExpression,
renderSystemExportSequenceBeforeExpression
} from '../../utils/systemJsRendering';
import { HasEffectsContext } from '../ExecutionContext';
import { EMPTY_PATH, ObjectPath } from '../utils/PathTracker';
Expand Down Expand Up @@ -32,48 +33,33 @@ export default class UpdateExpression extends NodeBase {
render(code: MagicString, options: RenderOptions): void {
this.argument.render(code, options);
if (options.format === 'system') {
const variable = this.argument.variable;
const exportNames = options.exportNamesByVariable.get(variable!);
if (exportNames && exportNames.length) {
const variable = this.argument.variable!;
const exportNames = options.exportNamesByVariable.get(variable);
if (exportNames) {
const _ = options.compact ? '' : ' ';
const name = variable!.getName();
if (this.prefix) {
if (exportNames.length === 1) {
code.overwrite(
this.start,
this.end,
`exports('${exportNames[0]}',${_}${this.operator}${name})`
);
renderSystemExportExpression(variable, this.start, this.end, code, options);
} else {
code.overwrite(
renderSystemExportSequenceAfterExpression(
variable,
this.start,
this.end,
`(${this.operator}${name},${_}${getSystemExportStatement(
[variable!],
options
)},${_}${name})`
this.parent.type !== NodeType.ExpressionStatement,
code,
options
);
}
} else if (exportNames.length > 1) {
code.overwrite(
this.start,
this.end,
`(${getSystemExportFunctionLeft([variable!], false, options)}${this.operator}${name}))`
);
} else {
let op;
switch (this.operator) {
case '++':
op = `${name}${_}+${_}1`;
break;
case '--':
op = `${name}${_}-${_}1`;
break;
}
code.overwrite(
const operator = this.operator[0];
renderSystemExportSequenceBeforeExpression(
variable,
this.start,
this.end,
`(exports('${exportNames[0]}',${_}${op}),${_}${name}${this.operator})`
this.parent.type !== NodeType.ExpressionStatement,
code,
options,
`${_}${operator}${_}1`
);
}
}
Expand Down
74 changes: 49 additions & 25 deletions src/ast/nodes/VariableDeclaration.ts
Expand Up @@ -9,8 +9,8 @@ import {
RenderOptions
} from '../../utils/renderHelpers';
import {
getSystemExportFunctionLeft,
getSystemExportStatement
getSystemExportStatement,
renderSystemExportExpression
} from '../../utils/systemJsRendering';
import { InclusionContext } from '../ExecutionContext';
import { EMPTY_PATH } from '../utils/PathTracker';
Expand Down Expand Up @@ -165,7 +165,12 @@ export default class VariableDeclaration extends NodeBase {
let separatorString = '',
leadingString,
nextSeparatorString;
const systemPatternExports: Variable[] = [];
const aggregatedSystemExports: Variable[] = [];
const singleSystemExport = gatherSystemExportsAndGetSingleExport(
separatedNodes,
options,
aggregatedSystemExports
);
for (const { node, start, separator, contentEnd, end } of separatedNodes) {
if (!node.included) {
code.remove(start, end);
Expand All @@ -186,27 +191,15 @@ export default class VariableDeclaration extends NodeBase {
}
isInDeclaration = false;
} else {
if (options.format === 'system' && node.init !== null) {
if (node.id.type !== NodeType.Identifier) {
node.id.addExportedVariables(systemPatternExports, options.exportNamesByVariable);
} else {
const exportNames = options.exportNamesByVariable.get(node.id.variable!);
if (exportNames) {
const _ = options.compact ? '' : ' ';
const operatorPos = findFirstOccurrenceOutsideComment(
code.original,
'=',
node.id.end
);
code.prependLeft(
findNonWhiteSpace(code.original, operatorPos + 1),
exportNames.length === 1
? `exports('${exportNames[0]}',${_}`
: getSystemExportFunctionLeft([node.id.variable!], false, options)
);
nextSeparatorString += ')';
}
}
if (singleSystemExport && singleSystemExport === node.id.variable) {
const operatorPos = findFirstOccurrenceOutsideComment(code.original, '=', node.id.end);
renderSystemExportExpression(
singleSystemExport,
findNonWhiteSpace(code.original, operatorPos + 1),
separator === null ? contentEnd : separator,
code,
options
);
}
if (isInDeclaration) {
separatorString += ',';
Expand Down Expand Up @@ -237,9 +230,40 @@ export default class VariableDeclaration extends NodeBase {
lastSeparatorPos,
actualContentEnd!,
renderedContentEnd,
systemPatternExports,
aggregatedSystemExports,
options,
isNoStatement
);
}
}

function gatherSystemExportsAndGetSingleExport(
separatedNodes: {
node: VariableDeclarator;
}[],
options: RenderOptions,
aggregatedSystemExports: Variable[]
): Variable | null {
let singleSystemExport: Variable | null = null;
if (options.format === 'system') {
for (const { node } of separatedNodes) {
if (
node.id instanceof Identifier &&
node.init &&
aggregatedSystemExports.length === 0 &&
options.exportNamesByVariable.get(node.id.variable!)?.length === 1
) {
singleSystemExport = node.id.variable!;
aggregatedSystemExports.push(singleSystemExport);
} else {
node.id.addExportedVariables(aggregatedSystemExports, options.exportNamesByVariable);
}
}
if (aggregatedSystemExports.length > 1) {
singleSystemExport = null;
} else if (singleSystemExport) {
aggregatedSystemExports.length = 0;
}
}
return singleSystemExport;
}
4 changes: 1 addition & 3 deletions src/finalisers/system.ts
Expand Up @@ -60,9 +60,7 @@ function getExportsBlock(

const getHoistedExportsBlock = (exports: ChunkExports, _: string, t: string, n: string): string =>
getExportsBlock(
exports
.filter(expt => expt.hoisted || expt.uninitialized)
.map(expt => ({ name: expt.exported, value: expt.uninitialized ? 'void 0' : expt.local })),
exports.filter(expt => expt.hoisted).map(expt => ({ name: expt.exported, value: expt.local })),
_,
t,
n
Expand Down

0 comments on commit 52ce573

Please sign in to comment.