public override AstNode ShallowClone() { var res = new AstVar(Source, Start, End); res.Definitions.AddRange(Definitions.AsReadOnlySpan()); return(res); }
public VariableDefinition(AstBlock parentBlock, AstNode parent, AstVar astVar, AstVarDef astVarDef, bool canMoveInitialization, int originalIndexInVar) { ParentBlock = parentBlock; Parent = parent; AstVar = astVar; CanMoveInitialization = canMoveInitialization; OriginalIndexInVar = originalIndexInVar; AstVarDef = astVarDef; }
/// If there is global variable named `global`, then define it as `window`, because we are bundling for browser static void IfNeededPolyfillGlobal(AstToplevel topLevelAst) { if (topLevelAst.Globals !.ContainsKey("global")) { var astVar = new AstVar(topLevelAst); astVar.Definitions.Add(new AstVarDef(new AstSymbolVar("global"), new AstSymbolRef("window"))); topLevelAst.Body.Insert(0) = astVar; } }
AstNode ParseForStatement(Position nodeStart) { Next(); EnterLexicalScope(); Expect(TokenType.ParenL); if (Type == TokenType.Semi) { return(ParseFor(nodeStart, null)); } var isLet = IsLet(); if (Type == TokenType.Var || Type == TokenType.Const || isLet) { var startLoc = Start; var kind = isLet ? VariableKind.Let : ToVariableKind((string)Value); Next(); var declarations = new StructList <AstVarDef>(); ParseVar(ref declarations, true, kind); AstDefinitions init; if (kind == VariableKind.Let) { init = new AstLet(this, startLoc, _lastTokEnd, ref declarations); } else if (kind == VariableKind.Const) { init = new AstConst(this, startLoc, _lastTokEnd, ref declarations); } else { init = new AstVar(this, startLoc, _lastTokEnd, ref declarations); } if ((Type == TokenType.In || Options.EcmaVersion >= 6 && IsContextual("of")) && init.Definitions.Count == 1 && !(kind != VariableKind.Var && init.Definitions[0].Value != null)) { return(ParseForIn(nodeStart, init)); } return(ParseFor(nodeStart, init)); } else { var refDestructuringErrors = new DestructuringErrors(); var init = ParseExpression(true, refDestructuringErrors); if (Type == TokenType.In || Options.EcmaVersion >= 6 && IsContextual("of")) { init = ToAssignable(init); CheckLVal(init, false, null); CheckPatternErrors(refDestructuringErrors, true); return(ParseForIn(nodeStart, init)); } CheckExpressionErrors(refDestructuringErrors, true); return(ParseFor(nodeStart, init)); } }
protected override AstNode?After(AstNode node, bool inList) { if (node is AstToplevel toplevel && _shadowedWindow) { var newVar = new AstVar(toplevel); var name = new AstSymbolVar("global"); newVar.Definitions.Add(new AstVarDef(toplevel, name, new AstSymbolRef("window"))); toplevel.Body.Insert(0) = newVar; } return(node); }
// Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see // the second parameter to `parseExpression`), and then check // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop. AstIterationStatement ParseForStatement(Position nodeStart) { Next(); var isAwait = EatContextual("await"); EnterLexicalScope(); Expect(TokenType.ParenL); if (Type == TokenType.Semi) { return(ParseFor(nodeStart, null, isAwait)); } var isLet = IsLet(); if (Type is TokenType.Var or TokenType.Const || isLet) { var startLoc = Start; var kind = isLet ? VariableKind.Let : ToVariableKind((string)GetValue()); Next(); var declarations = new StructList <AstVarDef>(); ParseVar(ref declarations, true, kind); AstDefinitions init; if (kind == VariableKind.Let) { init = new AstLet(SourceFile, startLoc, _lastTokEnd, ref declarations); } else if (kind == VariableKind.Const) { init = new AstConst(SourceFile, startLoc, _lastTokEnd, ref declarations); } else { init = new AstVar(SourceFile, startLoc, _lastTokEnd, ref declarations); } if ((Type == TokenType.In || IsContextual("of")) && init.Definitions.Count == 1 && !(kind != VariableKind.Var && init.Definitions[0].Value != null)) { return(ParseForIn(nodeStart, init, isAwait)); } return(ParseFor(nodeStart, init, isAwait)); }
protected override AstNode?Before(AstNode node, bool inList) { if (node.IsSymbolDef().IsGlobalSymbol() is {} symbolName) { if (symbolName == "global") { foreach (var parent in Parents()) { if (parent is AstScope scope) { if (scope.Variables !.ContainsKey("window") || scope.Functions !.ContainsKey("window")) { _shadowedWindow = true; return(null); } } } return(new AstSymbolRef(node, "window")); } } if (node is AstSimpleStatement simpleStatement && simpleStatement.Body is AstAssign assigment && assigment.Operator == Operator.Assignment) { if (assigment.Left is AstDot dot && dot.PropertyAsString == "exports" && dot.Expression.IsSymbolDef().IsGlobalSymbol() == "module") { var res = new AstVar(node); var newVar = new AstSymbolVar(assigment.Left, _varName); ResultingSymbol = newVar; res.Definitions.Add(new AstVarDef(assigment.Left, newVar, assigment.Right)); return(Transform(res)); } } return(null); }
public void Run() { var stopwatch = Stopwatch.StartNew(); foreach (var(splitName, mainFileList) in PartToMainFilesMap) { foreach (var mainFile in mainFileList) { if (_cache.TryGetValue(mainFile, out var sourceFile)) { MarkRequiredAs(sourceFile, splitName); continue; } Check(mainFile, splitName); } _splitMap[splitName] = new SplitInfo(splitName) { ShortName = _ctx.GenerateBundleName(splitName), PropName = "ERROR", IsMainSplit = true }; } stopwatch.Stop(); _ctx.ReportTime("Parse", stopwatch.Elapsed); foreach (var(_, sourceFile) in _cache) { foreach (var(file, path) in sourceFile.NeedsImports) { _cache.TryGetValue(file, out var targetFile); targetFile !.CreateWholeExport(path); } } var lazySplitCounter = 0; foreach (var f in _order) { var fullBundleName = f.PartOfBundle !; if (!_splitMap.TryGetValue(fullBundleName, out var split)) { var shortenedBundleName = _ctx.GenerateBundleName(fullBundleName); split = new SplitInfo(fullBundleName) { ShortName = shortenedBundleName, PropName = BundlerHelpers.NumberToIdent(lazySplitCounter++) }; _splitMap[fullBundleName] = split; } foreach (var dependency in f.PlainJsDependencies) { split.PlainJsDependencies.Add(dependency); } } if (lazySplitCounter > 0) { DetectBundleExportsImports(ref lazySplitCounter); } foreach (var(splitName, splitInfo) in _splitMap) { var topLevelAst = Parser.Parse(_ctx.JsHeaders(splitName, lazySplitCounter > 0)); if (GlobalDefines != null && GlobalDefines.Count > 0) { topLevelAst.Body.Add(Helpers.EmitVarDefines(GlobalDefines)); } topLevelAst.FigureOutScope(); foreach (var jsDependency in splitInfo.PlainJsDependencies) { var content = _ctx.ReadContent(jsDependency); var jsAst = Parser.Parse(content.Item1 !); content.Item2?.ResolveInAst(jsAst); jsAst.FigureOutScope(); BundlerHelpers.SimplifyJavaScriptDependency(jsAst); _currentFileIdent = BundlerHelpers.FileNameToIdent(jsDependency); BundlerHelpers.AppendToplevelWithRename(topLevelAst, jsAst, _currentFileIdent); } foreach (var sourceFile in _order) { if (sourceFile.PartOfBundle != splitName) { continue; } foreach (var keyValuePair in sourceFile.Ast.Globals !) { topLevelAst.Globals !.TryAdd(keyValuePair.Key, keyValuePair.Value); topLevelAst.NonRootSymbolNames?.Add(keyValuePair.Key); } } AddExternallyImportedFromOtherBundles(topLevelAst, splitInfo); foreach (var sourceFile in _order) { if (sourceFile.PartOfBundle != splitName) { continue; } _currentSourceFile = sourceFile; _currentFileIdent = BundlerHelpers.FileNameToIdent(sourceFile.Name); BundlerHelpers.AppendToplevelWithRename(topLevelAst, sourceFile.Ast, _currentFileIdent , BeforeAdd); } IfNeededPolyfillGlobal(topLevelAst); AddExportsFromLazyBundle(splitInfo, topLevelAst); BundlerHelpers.WrapByIIFE(topLevelAst); if (lazySplitCounter > 0 && PartToMainFilesMap.ContainsKey(splitName)) { var astVar = new AstVar(topLevelAst); astVar.Definitions.Add(new AstVarDef(new AstSymbolVar("__bbb"), new AstObject())); topLevelAst.Body.Insert(0) = astVar; } if (CompressOptions != null) { stopwatch = Stopwatch.StartNew(); topLevelAst.FigureOutScope(); topLevelAst = topLevelAst.Compress(CompressOptions, new ScopeOptions { TopLevel = false, BeforeMangling = IgnoreEvalInTwoScopes }); stopwatch.Stop(); _ctx.ReportTime("Compress", stopwatch.Elapsed); } if (Mangle) { stopwatch = Stopwatch.StartNew(); topLevelAst.Mangle(new ScopeOptions { FrequencyCounting = MangleWithFrequencyCounting, TopLevel = false, BeforeMangling = IgnoreEvalInTwoScopes }, OutputOptions); stopwatch.Stop(); _ctx.ReportTime("Mangle", stopwatch.Elapsed); } _ctx.ModifyBundle(splitInfo.ShortName !, topLevelAst); if (GenerateSourceMap) { stopwatch = Stopwatch.StartNew(); var builder = new SourceMapBuilder(); topLevelAst.PrintToBuilder(builder, OutputOptions); stopwatch.Stop(); _ctx.ReportTime("Print", stopwatch.Elapsed); _ctx.WriteBundle(splitInfo.ShortName !, builder); } else { stopwatch = Stopwatch.StartNew(); var content = topLevelAst.PrintToString(OutputOptions); stopwatch.Stop(); _ctx.ReportTime("Print", stopwatch.Elapsed); _ctx.WriteBundle(splitInfo.ShortName !, content); } } }
public void Run() { foreach (var(splitName, mainFileList) in PartToMainFilesMap) { foreach (var mainFile in mainFileList) { if (_cache.TryGetValue(mainFile, out var sourceFile)) { MarkRequiredAs(sourceFile, splitName); continue; } Check(mainFile, splitName); } _splitMap[splitName] = new SplitInfo(splitName) { ShortName = _ctx.GenerateBundleName(splitName), PropName = "ERROR", IsMainSplit = true }; } foreach (var(_, sourceFile) in _cache) { if (sourceFile.NeedsWholeExport && sourceFile.WholeExport == null) { sourceFile.CreateWholeExport(); } } var lazySplitCounter = 0; foreach (var f in _order) { var fullBundleName = f.PartOfBundle !; if (!_splitMap.TryGetValue(fullBundleName, out var split)) { var shortenedBundleName = _ctx.GenerateBundleName(fullBundleName); split = new SplitInfo(fullBundleName) { ShortName = shortenedBundleName, PropName = BundlerHelpers.NumberToIdent(lazySplitCounter++) }; _splitMap[fullBundleName] = split; } foreach (var dependency in f.PlainJsDependencies) { split.PlainJsDependencies.Add(dependency); } } if (lazySplitCounter > 0) { DetectBundleExportsImports(ref lazySplitCounter); } foreach (var(splitName, splitInfo) in _splitMap) { var topLevelAst = new Parser(new Options(), _ctx.JsHeaders(splitName, lazySplitCounter > 0)).Parse(); if (GlobalDefines != null && GlobalDefines.Count > 0) { topLevelAst.Body.Add(Helpers.EmitVarDefines(GlobalDefines)); } topLevelAst.FigureOutScope(); foreach (var jsDependency in splitInfo.PlainJsDependencies) { var jsAst = new Parser(new Options(), _ctx.ReadContent(jsDependency) !).Parse(); jsAst.FigureOutScope(); _currentFileIdent = BundlerHelpers.FileNameToIdent(jsDependency); BundlerHelpers.AppendToplevelWithRename(topLevelAst, jsAst, _currentFileIdent); } AddExternallyImportedFromOtherBundles(topLevelAst, splitInfo); foreach (var sourceFile in _order) { if (sourceFile.PartOfBundle != splitName) { continue; } _currentSourceFile = sourceFile; _currentFileIdent = BundlerHelpers.FileNameToIdent(sourceFile.Name); BundlerHelpers.AppendToplevelWithRename(topLevelAst, sourceFile.Ast, _currentFileIdent , BeforeAdd); } AddExportsFromLazyBundle(splitInfo, topLevelAst); BundlerHelpers.WrapByIIFE(topLevelAst); if (lazySplitCounter > 0 && PartToMainFilesMap.ContainsKey(splitName)) { var astVar = new AstVar(topLevelAst); astVar.Definitions.Add(new AstVarDef(new AstSymbolVar("__bbb"), new AstObject())); topLevelAst.Body.Insert(0) = astVar; } if (CompressOptions != null) { topLevelAst.FigureOutScope(); topLevelAst = topLevelAst.Compress(CompressOptions); } if (Mangle) { topLevelAst.Mangle(new ScopeOptions { FrequencyCounting = MangleWithFrequencyCounting, TopLevel = false, BeforeMangling = IgnoreEvalInTwoScopes }); } _ctx.WriteBundle(splitInfo.ShortName !, topLevelAst.PrintToString(OutputOptions)); } }