Пример #1
0
    public static (string outAst, string outMinJs, string outNiceJs)  CompressTestCore(CompressTestData testData, ICompressOptions options)
    {
        string outAst;
        var    outNiceJs = string.Empty;
        var    outMinJs  = string.Empty;

        try
        {
            var parser   = new Parser(new Options(), testData.InputContent);
            var toplevel = parser.Parse();
            toplevel.FigureOutScope();
            toplevel = toplevel.Compress(options);
            var strSink = new StringLineSink();
            var dumper  = new DumpAst(new AstDumpWriter(strSink));
            dumper.Walk(toplevel);
            outAst = strSink.ToString();
            var outMinJsBuilder = new SourceMapBuilder();
            toplevel.PrintToBuilder(outMinJsBuilder, new OutputOptions());
            outMinJs = outMinJsBuilder.Content();
            var outNiceJsBuilder = new SourceMapBuilder();
            toplevel.PrintToBuilder(outNiceJsBuilder, new OutputOptions {
                Beautify = true
            });
            outNiceJs = outNiceJsBuilder.Content();
        }
        catch (SyntaxError e)
        {
            outAst = e.Message;
        }

        return(outAst, outMinJs, outNiceJs);
    }
Пример #2
0
 public string ReadContent(string name)
 {
     if (!BuildResult.Path2FileInfo.TryGetValue(name, out var fileInfo))
     {
         throw new InvalidOperationException("Bundler ReadContent does not exists:" + name);
     }
     if (fileInfo.Type == FileCompilationType.ImportedCss || fileInfo.Type == FileCompilationType.Css)
     {
         return("");
     }
     if (fileInfo.Type == FileCompilationType.Json)
     {
         return(fileInfo.Owner.Utf8Content);
     }
     if (fileInfo.Type == FileCompilationType.JavaScriptAsset || fileInfo.Type == FileCompilationType.JavaScript || fileInfo.Type == FileCompilationType.EsmJavaScript)
     {
         return(fileInfo.Output);
     }
     if (fileInfo.Type == FileCompilationType.TypeScriptDefinition)
     {
         return("");
     }
     if (fileInfo.Type == FileCompilationType.TypeScript)
     {
         var sourceMapBuilder = new SourceMapBuilder();
         var adder            = sourceMapBuilder.CreateSourceAdder(fileInfo.Output, fileInfo.MapLink);
         var sourceReplacer   = new SourceReplacer();
         Project.ApplySourceInfo(sourceReplacer, fileInfo.SourceInfo, BuildResult);
         sourceReplacer.Apply(adder);
         return(sourceMapBuilder.Content());
     }
     throw new InvalidOperationException("Bundler Read Content unknown type " + Enum.GetName(typeof(FileCompilationType), fileInfo.Type) + ":" + name);
 }
Пример #3
0
        public void AddFile(
            string type,
            string filename,
            ArraySegment <byte> bytes,
            int?position = null,
            Dictionary <string, object> properties = null,
            SourceMapBuilder sourceMapBuilder      = null
            )
        {
            lock (Files) {
                if (position.HasValue)
                {
                    FileOrder.Insert(position.Value, filename);
                }
                else
                {
                    FileOrder.Add(filename);
                }

                Files.Add(filename, new ResultFile {
                    Type             = type,
                    Filename         = filename,
                    Contents         = bytes,
                    Size             = bytes.Count,
                    Properties       = properties,
                    SourceMapBuilder = sourceMapBuilder
                });
            }
        }
Пример #4
0
        public void PrintToBuilder(SourceMapBuilder builder, OutputOptions?options = null)
        {
            var o = new OutputContext(options, builder);

            Print(o);
            builder.AddMapping(null, 0, 0, false);
        }
Пример #5
0
        public void GivenAMapExistsForTheTheCSVFileSource()
        {
            var map = new SourceMapBuilder()
                      .WithIndex(0)
                      .WithDataType(typeof(string))
                      .Build();

            _appContext.CsvFileSource.SetMaps(new List <SourceMap> {
                map
            });
        }
Пример #6
0
    string Optimize(string input, ICompressOptions compressOptions)
    {
        var parser   = new Parser(new Options(), input);
        var toplevel = parser.Parse();

        toplevel = toplevel.Compress(compressOptions);
        var outMinJsBuilder = new SourceMapBuilder();

        toplevel.PrintToBuilder(outMinJsBuilder, new OutputOptions());
        return(outMinJsBuilder.Content());
    }
Пример #7
0
        public void WriteBundle(string name, SourceMapBuilder content)
        {
            content.AddText("//# sourceMappingURL=" + name + ".map");
            var source = content.Content();
            var sm     = content.Build(_mainBuildResult.CommonSourceDirectory, SourceMapSourceRoot ?? "..").ToString();

            _logger.Info("Bundler created " + name + " with " + source.Length + " chars and sourcemap with " +
                         sm.Length + " chars");
            _mainBuildResult.FilesContent.GetOrAddValueRef(name)          = source;
            _mainBuildResult.FilesContent.GetOrAddValueRef(name + ".map") = sm;
        }
Пример #8
0
    public static SourceMap Identity(string content, string fileName)
    {
        var sb = new StringBuilder();

        sb.Append("AAAA");
        var endsWithNL = SourceMapBuilder.EndsWithNewLine(content);
        var len        = content.Length - (endsWithNL ? 1 : 0);

        for (var i = 0; i < len; i++)
        {
            if (content[i] == '\n')
            {
                sb.Append(";AACA");
            }
        }
        if (endsWithNL)
        {
            sb.Append(';');
        }
        return(new(new() { fileName })
        {
            mappings = sb.ToString()
        });
Пример #9
0
        public void SourceMapBuilder_BuildWorks()
        {
            var builder = new SourceMapBuilder(
                "test.map",
                @"C:\AC\ACD",
                @"C:\A\AB");

            builder.AddMapping(1, 11, new SourceLocation(@"C:\AC\ACD\sourceUrl1", "sourceName1", 10, 10));
            builder.AddMapping(2, 21, new SourceLocation(@"C:\AC\ACD\X\sourceUrl2", "sourceName2", 20, 20));
            builder.AddMapping(3, 31, new SourceLocation(@"C:\AC\ACD\Y\Z\sourceUrl3", "sourceName3", 30, 30));
            builder.AddMapping(4, 41, new SourceLocation(@"C:\B\sourceUrl4", "sourceName4", 40, 40));
            builder.AddMapping(5, 51, new SourceLocation(@"C:\A\AB\ABE\sourceUrl5", "sourceName5", 50, 50));
            builder.AddMapping(6, 61, new SourceLocation(@"C:\A\AB\AB F\sourceUrl6", "sourceName6", 60, 60));

            var map = builder.Build(
                new[]
            {
                "1", "2", "3", "4", "5", "6"
            });

            var expectedMap = StringHelper.CombineLinesNL
                              (
                "{",
                "  \"version\": 3,",
                "  \"file\": \"test.map\",",
                "  \"sourceRoot\": \"C:\\AC\\ACD\",",
                "  \"sources\": [\"../../AC/ACD/sourceUrl1\",\"../../AC/ACD/X/sourceUrl2\",\"../../AC/ACD/Y/Z/sourceUrl3\",\"../../B/sourceUrl4\",\"ABE/sourceUrl5\",\"AB F/sourceUrl6\"],",
                "  \"names\": [\"sourceName1\",\"sourceName2\",\"sourceName3\",\"sourceName4\",\"sourceName5\",\"sourceName6\"],",
                "  \"mappings\": \";WAUUA;qBCUUC;+BCUUC;yCCUUC;mDCUUC;6DCUUC\",",
                "  \"sourcesContent\": [\"1\",\"2\",\"3\",\"4\",\"5\",\"6\"]",
                "}"
                              );

            expectedMap = TextHelper.NormilizeEols(expectedMap, UnicodeNewline.LF);

            Assert.AreEqual(expectedMap, map);
        }
Пример #10
0
 public SourceMapTextAdder(SourceMapBuilder owner, string content, SourceMap sourceMap)
 {
     _owner       = owner;
     _iterator    = new SourceMapIterator(content, sourceMap);
     _sourceRemap = new StructList <int>();
     ref var ownerSources = ref owner._sources;
Пример #11
0
 public PlainTextAdder(SourceMapBuilder owner, string content)
 {
     _owner   = owner;
     _content = content;
 }
Пример #12
0
        public void Build(string sourceRoot, bool testProj = false, bool allowIncremental = true)
        {
            _versionDirPrefix = "";
            var coverage = _project.CoverageEnabled;

            if (coverage)
            {
                allowIncremental = false;
            }
            if (_mainBuildResult.OutputSubDir != null)
            {
                _versionDirPrefix = _mainBuildResult.OutputSubDir + "/";
            }
            var root             = _mainBuildResult.CommonSourceDirectory;
            var incremental      = _buildResult.Incremental && allowIncremental;
            var start            = DateTime.UtcNow;
            var sourceMapBuilder = new SourceMapBuilder();

            if (_project.Localize)
            {
                if (!incremental)
                {
                    sourceMapBuilder.AddText(
                        $"function g11nPath(s){{return\"./{_mainBuildResult.OutputSubDirPrefix}\"+s.toLowerCase()+\".js\"}};");
                    if (_project.DefaultLanguage != null)
                    {
                        sourceMapBuilder.AddText($"var g11nLoc=\"{_project.DefaultLanguage}\";");
                    }
                }
            }

            if (_project.SpriteGeneration)
            {
                _bundlePng = _project.BundlePngUrl;
                var bundlePngContent = _project.SpriteGenerator.BuildImage(false);
                if (bundlePngContent != null)
                {
                    _bundlePngInfo = new List <float>();
                    foreach (var slice in bundlePngContent)
                    {
                        _mainBuildResult.FilesContent.GetOrAddValueRef(
                            PathUtils.InjectQuality(_bundlePng, slice.Quality)) = slice.Content;
                        _bundlePngInfo.Add(slice.Quality);
                    }
                }
                else
                {
                    _bundlePng = null;
                }
            }

            if (_bundlePng != null && !incremental)
            {
                sourceMapBuilder.AddText(_mainBuildResult.GenerateCodeForBobrilBPath(_bundlePng, _bundlePngInfo));
            }

            if (!incremental)
            {
                sourceMapBuilder.AddText(_tools.LoaderJs);
                sourceMapBuilder.AddText(GetGlobalDefines());
                sourceMapBuilder.AddText(GetModuleMap());
                sourceMapBuilder.AddText(BundlerHelpers.JsHeaders(false));
            }

            var cssLink = "";

            var sortedResultSet = incremental
                ? _buildResult.RecompiledIncrementally.OrderBy(f => f.Owner.FullPath).ToArray()
                : _buildResult.Path2FileInfo.Values.OrderBy(f => f.Owner.FullPath).ToArray();

            if (!incremental)
            {
                foreach (var source in _buildResult.JavaScriptAssets)
                {
                    sourceMapBuilder.AddSource(source.Output, source.MapLink);
                }
            }

            foreach (var source in sortedResultSet)
            {
                if (source.Type is FileCompilationType.TypeScript or FileCompilationType.EsmJavaScript or FileCompilationType.JavaScript)
                {
                    if (source.Output == null)
                    {
                        continue; // Skip d.ts
                    }
                    var moduleName = source.Owner !.FullPath;
                    if (source.Type is FileCompilationType.TypeScript or FileCompilationType.EsmJavaScript or
                        FileCompilationType.JavaScript)
                    {
                        moduleName = PathUtils.WithoutExtension(moduleName);
                    }
                    sourceMapBuilder.AddText(
                        $"R('{PathUtils.Subtract(moduleName, root!)}',function(require, module, exports, global){{");
                    var adder          = sourceMapBuilder.CreateSourceAdder(source.Output, source.MapLink);
                    var sourceReplacer = new SourceReplacer();
                    _project.ApplySourceInfo(sourceReplacer, source.SourceInfo, _buildResult);
                    sourceReplacer.Apply(adder);
                    sourceMapBuilder.AddText("\n});");
                }
Пример #13
0
        private static void WriteBytesToFile(string folder, string name, ArraySegment <byte> bytes, SourceMapBuilder sourceMapBuilder = null)
        {
            var filePath = Path.Combine(folder, name);
            var fileMode = File.Exists(filePath) ? FileMode.Truncate : FileMode.CreateNew;

            EnsureDirectoryExists(Path.GetDirectoryName(filePath));

            bool writeMapLink = sourceMapBuilder != null && sourceMapBuilder.Build(folder, name);

            using (var fs = File.Open(filePath, fileMode, FileAccess.Write, FileShare.Read))
            {
                fs.Write(bytes.Array, bytes.Offset, bytes.Count);
                if (writeMapLink)
                {
                    sourceMapBuilder.WriteSourceMapLink(fs, folder, name);
                }
                fs.Flush();
            }
        }
Пример #14
0
        public (string?, SourceMap?) ReadContent(string name)
        {
            if (name == "<empty>")
            {
                return("module.exports = {};", null);
            }
            if (!_buildResult.Path2FileInfo.TryGetValue(name, out var fileInfo))
            {
                throw new InvalidOperationException("Bundler ReadContent does not exists:" + name);
            }

            if (fileInfo.Type == FileCompilationType.ImportedCss || fileInfo.Type == FileCompilationType.Css)
            {
                return("", null);
            }
            if (fileInfo.Type == FileCompilationType.Json)
            {
                if (BuildSourceMap)
                {
                    return(fileInfo.Owner.Utf8Content,
                           SourceMap.Identity(fileInfo.Owner.Utf8Content, fileInfo.Owner.FullPath));
                }
                return(fileInfo.Owner.Utf8Content, null);
            }

            if (fileInfo.Type == FileCompilationType.JavaScriptAsset ||
                fileInfo.Type == FileCompilationType.JavaScript)
            {
                if (BuildSourceMap)
                {
                    return(fileInfo.Output, SourceMap.Identity(fileInfo.Output, fileInfo.Owner.FullPath));
                }
                return(fileInfo.Output, null);
            }

            if (fileInfo.Type == FileCompilationType.TypeScriptDefinition)
            {
                return("", null);
            }

            if (fileInfo.Type is FileCompilationType.TypeScript or FileCompilationType.EsmJavaScript)
            {
                if (BuildSourceMap)
                {
                    var sourceMapBuilder = new SourceMapBuilder();
                    var adder            = sourceMapBuilder.CreateSourceAdder(fileInfo.Output, fileInfo.MapLink);
                    var sourceReplacer   = new SourceReplacer();
                    _project.ApplySourceInfo(sourceReplacer, fileInfo.SourceInfo, _buildResult);
                    sourceReplacer.Apply(adder);
                    return(sourceMapBuilder.Content(), sourceMapBuilder.Build(".", "."));
                }
                else
                {
                    var sourceMapBuilder = new SourceMapBuilder();
                    var adder            = sourceMapBuilder.CreateSourceAdder(fileInfo.Output, fileInfo.MapLink);
                    var sourceReplacer   = new SourceReplacer();
                    _project.ApplySourceInfo(sourceReplacer, fileInfo.SourceInfo, _buildResult);
                    sourceReplacer.Apply(adder);
                    return(sourceMapBuilder.Content(), null);
                }
            }

            throw new InvalidOperationException("Bundler Read Content unknown type " +
                                                Enum.GetName(typeof(FileCompilationType), fileInfo.Type) + ":" + name);
        }
Пример #15
0
    ParseTestCore(
        ParserTestData testData)
    {
        string outAst;
        var    outMinJs     = string.Empty;
        var    outMinJsMap  = string.Empty;
        var    outNiceJs    = string.Empty;
        var    outNiceJsMap = string.Empty;

        try
        {
            var comments        = new List <(bool block, string content, SourceLocation location)>();
            var commentListener = new CommentListener();
            var parser          = new Parser(
                new()
            {
                SourceFile = testData.SourceName, EcmaVersion = testData.EcmaScriptVersion, OnComment =
                    (block, content, location) =>
                {
                    commentListener.OnComment(block, content, location);
                    comments.Add((block, content, location));
                },
                SourceType = testData.SourceName.StartsWith("module-") ? SourceType.Module : SourceType.Script
            },
                testData.Input);
            var toplevel = parser.Parse();
            commentListener.Walk(toplevel);
            SourceMap?inputSourceMap = null;
            if (testData.InputSourceMap != null)
            {
                inputSourceMap = SourceMap.Parse(testData.InputSourceMap, ".");
                inputSourceMap.ResolveInAst(toplevel);
            }

            var strSink = new StringLineSink();
            toplevel.FigureOutScope();
            var dumper = new DumpAst(new AstDumpWriter(strSink));
            dumper.Walk(toplevel);
            foreach (var(block, content, location) in comments)
            {
                strSink.Print(
                    $"{(block ? "Block" : "Line")} Comment ({location.Start.ToShortString()}-{location.End.ToShortString()}): {content}");
            }

            outAst = strSink.ToString();
            var outMinJsBuilder = new SourceMapBuilder();
            var outputOptions   = new OutputOptions
            {
                Shorthand = testData.EcmaScriptVersion >= 6
            };
            toplevel.PrintToBuilder(outMinJsBuilder, outputOptions);
            outMinJsBuilder.AddText(
                $"//# sourceMappingURL={PathUtils.ChangeExtension(testData.SourceName, "minjs.map")}");
            if (inputSourceMap != null)
            {
                outMinJsBuilder.AttachSourcesContent(inputSourceMap);
            }
            outMinJs    = outMinJsBuilder.Content();
            outMinJsMap = outMinJsBuilder.Build(".", ".").ToString();
            var outNiceJsBuilder = new SourceMapBuilder();
            outputOptions = new()
            {
                Beautify  = true,
                Shorthand = testData.EcmaScriptVersion >= 6
            };
            toplevel.PrintToBuilder(outNiceJsBuilder, outputOptions);
            outNiceJsBuilder.AddText(
                $"//# sourceMappingURL={PathUtils.ChangeExtension(testData.SourceName, "nicejs.map")}");
            if (inputSourceMap != null)
            {
                outNiceJsBuilder.AttachSourcesContent(inputSourceMap);
            }
            outNiceJs    = outNiceJsBuilder.Content();
            outNiceJsMap = outNiceJsBuilder.Build(".", ".").ToString();

            strSink = new StringLineSink();
            toplevel.FigureOutScope();
            dumper = new DumpAst(new AstDumpWriter(strSink));
            dumper.Walk(toplevel);
            var beforeClone = strSink.ToString();
            toplevel = toplevel.DeepClone();
            strSink  = new StringLineSink();
            toplevel.FigureOutScope();
            dumper = new DumpAst(new AstDumpWriter(strSink));
            dumper.Walk(toplevel);
            var afterClone = strSink.ToString();
            if (beforeClone != afterClone)
            {
                throw new Exception("Dump of clone is not identical");
            }

            toplevel.Mangle();
        }
        catch (SyntaxError e)
        {
            outAst = e.Message;
        }

        return(outAst, outMinJs, outMinJsMap, outNiceJs, outNiceJsMap);
    }
Пример #16
0
        public void Build(string sourceRoot, bool testProj = false, bool allowIncremental = true)
        {
            _versionDirPrefix = "";
            var coverage = _project.CoverageEnabled;

            if (coverage)
            {
                allowIncremental = false;
            }
            if (_mainBuildResult.OutputSubDir != null)
            {
                _versionDirPrefix = _mainBuildResult.OutputSubDir + "/";
            }
            var root             = _mainBuildResult.CommonSourceDirectory;
            var incremental      = _buildResult.Incremental && allowIncremental;
            var start            = DateTime.UtcNow;
            var sourceMapBuilder = new SourceMapBuilder();

            if (_project.Localize)
            {
                if (!incremental)
                {
                    sourceMapBuilder.AddText(
                        $"function g11nPath(s){{return\"./{_mainBuildResult.OutputSubDirPrefix}\"+s.toLowerCase()+\".js\"}};");
                    if (_project.DefaultLanguage != null)
                    {
                        sourceMapBuilder.AddText($"var g11nLoc=\"{_project.DefaultLanguage}\";");
                    }
                }
            }

            if (_project.SpriteGeneration)
            {
                _bundlePng = _project.BundlePngUrl;
                var bundlePngContent = _project.SpriteGenerator.BuildImage(false);
                if (bundlePngContent != null)
                {
                    _bundlePngInfo = new List <float>();
                    foreach (var slice in bundlePngContent)
                    {
                        _mainBuildResult.FilesContent.GetOrAddValueRef(
                            PathUtils.InjectQuality(_bundlePng, slice.Quality)) = slice.Content;
                        _bundlePngInfo.Add(slice.Quality);
                    }
                }
                else
                {
                    _bundlePng = null;
                }
            }

            if (_bundlePng != null && !incremental)
            {
                sourceMapBuilder.AddText(_mainBuildResult.GenerateCodeForBobrilBPath(_bundlePng, _bundlePngInfo));
            }

            if (!incremental)
            {
                sourceMapBuilder.AddText(_tools.LoaderJs);
                sourceMapBuilder.AddText(GetGlobalDefines());
                sourceMapBuilder.AddText(GetModuleMap());
                sourceMapBuilder.AddText(BundlerHelpers.JsHeaders(false));
            }

            var cssLink = "";

            var sortedResultSet = incremental
                ? _buildResult.RecompiledIncrementaly.OrderBy(f => f.Owner.FullPath).ToArray()
                : _buildResult.Path2FileInfo.Values.OrderBy(f => f.Owner.FullPath).ToArray();

            if (!incremental)
            {
                foreach (var source in _buildResult.JavaScriptAssets)
                {
                    sourceMapBuilder.AddSource(source.Output, source.MapLink);
                }
            }

            foreach (var source in sortedResultSet)
            {
                if (source.Type == FileCompilationType.TypeScript ||
                    source.Type == FileCompilationType.EsmJavaScript ||
                    source.Type == FileCompilationType.JavaScript)
                {
                    if (source.Output == null)
                    {
                        continue; // Skip d.ts
                    }
                    sourceMapBuilder.AddText(
                        $"R('{PathUtils.Subtract(PathUtils.WithoutExtension(source.Owner.FullPath), root)}',function(require, module, exports, global){{");
                    var adder          = sourceMapBuilder.CreateSourceAdder(source.Output, source.MapLink);
                    var sourceReplacer = new SourceReplacer();
                    _project.ApplySourceInfo(sourceReplacer, source.SourceInfo, _buildResult);
                    sourceReplacer.Apply(adder);
                    sourceMapBuilder.AddText("\n});");
                }
                else if (source.Type == FileCompilationType.Json)
                {
                    sourceMapBuilder.AddText(
                        $"R('{PathUtils.Subtract(source.Owner.FullPath, root)}',");
                    sourceMapBuilder.AddText(source.Owner.Utf8Content);
                    sourceMapBuilder.AddText(");");
                }
                else if (source.Type == FileCompilationType.ImportedCss)
                {
                    sourceMapBuilder.AddText(
                        $"R('{PathUtils.Subtract(source.Owner.FullPath, root)}',function(){{}});");
                    string cssPath = _buildResult.ToOutputUrl(source);
                    _mainBuildResult.FilesContent.GetOrAddValueRef(cssPath) = source.Output;
                    cssLink += "<link rel=\"stylesheet\" href=\"" + cssPath + "\">";
                }
                else if (source.Type == FileCompilationType.Css)
                {
                    string cssPath = _buildResult.ToOutputUrl(source);
                    _mainBuildResult.FilesContent.GetOrAddValueRef(cssPath) = source.Output;
                    cssLink += "<link rel=\"stylesheet\" href=\"" + cssPath + "\">";
                }
                else if (source.Type == FileCompilationType.Resource)
                {
                    _mainBuildResult.FilesContent.GetOrAddValueRef(_buildResult.ToOutputUrl(source)) =
                        source.Owner.ByteContent;
                }
            }

            if (!testProj && _project.NoHtml)
            {
                sourceMapBuilder.AddText(RequireBobril());
                if (_project.MainFile != null)
                {
                    sourceMapBuilder.AddText(
                        $"R.r('./{PathUtils.WithoutExtension(PathUtils.Subtract(_project.MainFile, root))}');");
                }
            }

            if (_project.Localize)
            {
                _project.TranslationDb.BuildTranslationJs(_tools, _mainBuildResult.FilesContent,
                                                          _mainBuildResult.OutputSubDir);
            }

            if (incremental)
            {
                sourceMapBuilder.AddText("//# sourceMappingURL=bundle2.js.map");
                _sourceMap2       = sourceMapBuilder.Build(root, sourceRoot);
                _sourceMap2String = _sourceMap2.ToString();
                _bundle2Js        = sourceMapBuilder.Content();
                _project.Owner.Logger.Info("JS Bundle length: " + _bundleJs.Length + " SourceMap length: " +
                                           _sourceMapString.Length + " Delta: " + _bundle2Js.Length + " SM:" +
                                           _sourceMap2String.Length + " T:" +
                                           (DateTime.UtcNow - start).TotalMilliseconds.ToString("F0") + "ms");
            }
            else
            {
                sourceMapBuilder.AddText("//# sourceMappingURL=" + PathUtils.GetFile(_buildResult.BundleJsUrl) +
                                         ".map");
                if (coverage)
                {
                    _sourceMap = sourceMapBuilder.Build(".", ".");
                    _bundleJs  = sourceMapBuilder.Content();
                    var toplevel = Parser.Parse(_bundleJs);
                    _sourceMap.ResolveInAst(toplevel);
                    var coverageInst = new CoverageInstrumentation();
                    coverageInst.RealPath            = PathUtils.RealPath;
                    _project.CoverageInstrumentation = coverageInst;
                    toplevel = coverageInst.Instrument(toplevel);
                    coverageInst.AddCountingHelpers(toplevel);
                    coverageInst.CleanUp(new SourceReader(_project.Owner.DiskCache,
                                                          _mainBuildResult.CommonSourceDirectory));
                    if (_project.MainFile != null)
                    {
                        MarkImportant(_project.MainFile, _buildResult, new HashSet <string>(), coverageInst);
                    }
                    sourceMapBuilder = new SourceMapBuilder();
                    toplevel.PrintToBuilder(sourceMapBuilder, new OutputOptions {
                        Beautify = true
                    });
                    sourceMapBuilder.AddText("//# sourceMappingURL=" + PathUtils.GetFile(_buildResult.BundleJsUrl) +
                                             ".map");
                }

                _sourceMap = sourceMapBuilder.Build(root, sourceRoot);
                _bundleJs  = sourceMapBuilder.Content();

                _sourceMapString  = _sourceMap.ToString();
                _sourceMap2       = null;
                _sourceMap2String = null;
                _bundle2Js        = null;
                _cssLink          = cssLink;
                _project.Owner.Logger.Info("JS Bundle length: " + _bundleJs.Length + " SourceMap length: " +
                                           _sourceMapString.Length + " T:" +
                                           (DateTime.UtcNow - start).TotalMilliseconds.ToString("F0") + "ms");
            }

            _mainBuildResult.FilesContent.GetOrAddValueRef(_buildResult.BundleJsUrl)          = _bundleJs;
            _mainBuildResult.FilesContent.GetOrAddValueRef(_buildResult.BundleJsUrl + ".map") = _sourceMapString;
            if (incremental)
            {
                _mainBuildResult.FilesContent.GetOrAddValueRef(_versionDirPrefix + "bundle2.js")     = _bundle2Js;
                _mainBuildResult.FilesContent.GetOrAddValueRef(_versionDirPrefix + "bundle2.js.map") =
                    _sourceMap2String;
                SourceMaps = new Dictionary <string, SourceMap>
                {
                    { PathUtils.GetFile(_buildResult.BundleJsUrl), _sourceMap },
                    { "bundle2.js", _sourceMap2 }
                };
            }
            else
            {
                SourceMaps = new Dictionary <string, SourceMap>
                {
                    { PathUtils.GetFile(_buildResult.BundleJsUrl), _sourceMap }
                };
            }

            if (_project.SubProjects != null)
            {
                var newSubBundlers = new RefDictionary <string, FastBundleBundler>();
                foreach (var(projPath, subProject) in _project.SubProjects.OrderBy(a =>
                                                                                   a.Value?.Variant == "serviceworker"))
                {
                    if (subProject == null)
                    {
                        continue;
                    }
                    if (_subBundlers == null || !_subBundlers.TryGetValue(projPath, out var subBundler))
                    {
                        subBundler = new FastBundleBundler(_tools, _mainBuildResult, subProject,
                                                           _buildResult.SubBuildResults.GetOrFakeValueRef(projPath));
                    }

                    newSubBundlers.GetOrAddValueRef(projPath) = subBundler;
                    subBundler.Build(sourceRoot, false, false);
                }

                _subBundlers = newSubBundlers;
            }
            else
            {
                _subBundlers = null;
            }
        }
Пример #17
0
    public static Dictionary <string, string> BobrilSourceInfoTestCore(BobrilSourceInfoTestData testData)
    {
        var output = new Dictionary <string, string>();

        var source   = SourceMap.RemoveLinkToSourceMap(testData.InputContent["index.js"]);
        var toplevel = Parser.Parse(source);

        toplevel.FigureOutScope();
        var files      = new InMemoryImportResolver();
        var ctx        = new ResolvingConstEvalCtx("index.js", files);
        var sourceInfo = GatherBobrilSourceInfo.Gather(toplevel, ctx,
                                                       (myctx, text) =>
        {
            if (text.StartsWith('.'))
            {
                return(PathUtils.Join(PathUtils.Parent(myctx.SourceName), text));
            }
            return(text);
        });

        var builder = new SourceMapBuilder();
        var adder   = builder.CreateSourceAdder(source,
                                                testData.InputContent.ContainsKey("index.js.map")
                ? SourceMap.Parse(testData.InputContent["index.js.map"], ".")
                : null);
        var sourceReplacer = new SourceReplacer();

        ProcessReplacements(sourceReplacer, sourceInfo);
        sourceReplacer.Apply(adder);
        builder.AddText("//# sourceMappingURL=index.js.map");
        output["index.sourceinfo.json"] = JsonSerializer
                                          .Serialize(sourceInfo, new JsonSerializerOptions {
            WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
        })
                                          .Replace("\r\n", "\n");
        output["index.js"]     = builder.Content();
        output["index.js.map"] = builder.Build(".", "..").ToString();

        if (testData.InputContent.ContainsKey("index.js.map"))
        {
            SourceMap.Parse(testData.InputContent["index.js.map"], ".").ResolveInAst(toplevel);
        }

        var coverageInstrumentation = new CoverageInstrumentation();

        toplevel = coverageInstrumentation.Instrument(toplevel);
        coverageInstrumentation.AddCountingHelpers(toplevel);

        coverageInstrumentation.CleanUp(new TestUtf8Reader(testData.InputContent));

        builder = new SourceMapBuilder();
        toplevel.PrintToBuilder(builder, new OutputOptions {
            Beautify = true
        });
        builder.AddText("//# sourceMappingURL=cov.js.map");
        output["cov.info.json"] = JsonSerializer
                                  .Serialize(coverageInstrumentation.InstrumentedFiles,
                                             new JsonSerializerOptions {
            WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
        })
                                  .Replace("\r\n", "\n");
        output["cov.js"]     = builder.Content();
        output["cov.js.map"] = builder.Build(".", "..").ToString();

        return(output);
    }
Пример #18
0
        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);
                }
            }
        }
Пример #19
0
        static void Test2()
        {
            SourceMaps.List <SourceFile> sources = new SourceMaps.List <SourceFile>();

            sources.Add(new SourceFile("http://www.mysite.com/source1.txt", LoadFromFile(@"..\..\..\Website\source1.txt")));
            sources.Add(new SourceFile("http://www.mysite.com/source2.txt", LoadFromFile(@"..\..\..\Website\source2.txt")));

            string destfile = "";

            foreach (var sf in sources)
            {
                destfile += sf.content.ToLower();
            }
            destfile += "\r\n//# sourceMappingURL=myapp.js.map";

            SaveToFile(@"..\..\..\Website\myapp.js", destfile);

            SourceFile target = new SourceFile("http://www.mysite.com/myapp.js", destfile);

            // build tokens/source map entries
            SourceMaps.List <SourceMapEntry> sme = new SourceMaps.List <SourceMapEntry>();

            // this will map every single character, no name specified
            int cumulative_l = 0;

            foreach (var sf in sources)
            {
                for (int cx = 0; cx < sf.content.Length; cx++)
                {
                    string c   = ""; //sf.content[cx].ToString();
                    var    tok = new TokenSourceFileLocation(sf, c, cx);
                    sme.add(new SourceMapEntry(tok, cx + cumulative_l));
                }
                cumulative_l += sf.length;
            }

            // this maps only identifiers

            /*
             * Regex R = new Regex(@"[_a-zA-Z][_a-zA-Z0-9]*");
             * int cumulative_l = 0;
             * foreach(var sf in sources)
             * {
             * MatchCollection mc = R.Matches(sf.content);
             * foreach(Match match in mc)
             * {
             *    var keyword = match.Value.ToLower();
             *
             *    var tok = new TokenSourceFileLocation(sf, match.Value.ToLower(), match.Index);
             *    sme.add( new SourceMapEntry(tok,match.Index+cumulative_l));
             * }
             * cumulative_l += sf.length;
             * }
             */

            Uri sourceMapUri = Uri.parse("http://www.mysite.com/myapp.map");
            Uri fileUri      = Uri.parse("http://www.mysite.com/myapp.js");

            SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(sourceMapUri, fileUri, target);

            foreach (var e in sme)
            {
                sourceMapBuilder.addMapping(e.targetOffset, e.sourceLocation);
            }
            String sourceMap = sourceMapBuilder.build();

            SaveToFile(@"..\..\..\Website\myapp.js.map", sourceMap);
        }
Пример #20
0
        public void Build(string sourceRoot, string mapUrl, bool testProj = false)
        {
            _versionDirPrefix = "";
            if (Project.OutputSubDir != null)
            {
                _versionDirPrefix = Project.OutputSubDir + "/";
            }
            var root = Project.CommonSourceDirectory;

            if (root == null)
            {
                return;
            }
            var sourceMapBuilder = new SourceMapBuilder();

            if (!testProj && Project.NoHtml)
            {
                sourceMapBuilder.AddText(GetInitG11nCode());
                sourceMapBuilder.AddText(_tools.LoaderJs);
                sourceMapBuilder.AddText(GetGlobalDefines());
                sourceMapBuilder.AddText(GetModuleMap());
            }

            sourceMapBuilder.AddText(_tools.TsLibSource);
            var cssLink = "";

            foreach (var source in BuildResult.Path2FileInfo)
            {
                if (source.Value.Type == FileCompilationType.JavaScriptAsset)
                {
                    sourceMapBuilder.AddSource(source.Value.Output, source.Value.MapLink);
                }
            }

            foreach (var source in BuildResult.Path2FileInfo)
            {
                if (source.Value.Type == FileCompilationType.TypeScript ||
                    source.Value.Type == FileCompilationType.JavaScript)
                {
                    if (source.Value.Output == null)
                    {
                        continue; // Skip d.ts
                    }
                    sourceMapBuilder.AddText(
                        $"R('{PathUtils.Subtract(PathUtils.WithoutExtension(source.Key), root)}',function(require, module, exports, global){{");
                    sourceMapBuilder.AddSource(source.Value.Output, source.Value.MapLink);
                    sourceMapBuilder.AddText("});");
                }
                else if (source.Value.Type == FileCompilationType.Css)
                {
                    string cssPath = source.Value.OutputUrl;
                    FilesContent[cssPath] = source.Value.Output;
                    cssLink += "<link rel=\"stylesheet\" href=\"" + cssPath + "\">";
                }
                else if (source.Value.Type == FileCompilationType.Resource)
                {
                    FilesContent[source.Value.OutputUrl] = source.Value.Owner.ByteContent;
                }
            }

            if (Project.SpriteGeneration)
            {
                _bundlePng = Project.BundlePngUrl;
                var bundlePngContent = Project.SpriteGenerator.BuildImage(false);
                if (bundlePngContent != null)
                {
                    _bundlePngInfo = new List <float>();
                    foreach (var slice in bundlePngContent)
                    {
                        FilesContent[PathUtils.InjectQuality(_bundlePng, slice.Quality)] = slice.Content;
                        _bundlePngInfo.Add(slice.Quality);
                    }
                }
                else
                {
                    _bundlePng = null;
                }
            }

            if (!testProj && Project.NoHtml)
            {
                sourceMapBuilder.AddText(RequireBobril());
                sourceMapBuilder.AddText(
                    $"R.r('{PathUtils.WithoutExtension(PathUtils.Subtract(Project.MainFile, root))}');");
            }

            sourceMapBuilder.AddText("//# sourceMappingURL=" + mapUrl);
            _sourceMap       = sourceMapBuilder.Build(root, sourceRoot);
            _sourceMapString = _sourceMap.ToString();
            _bundleJs        = sourceMapBuilder.Content();
            if (!testProj && !Project.NoHtml && Project.ExampleSources.Count > 0)
            {
                if (Project.ExampleSources.Count == 1)
                {
                    BuildFastBundlerIndexHtml(
                        PathUtils.WithoutExtension(PathUtils.Subtract(Project.ExampleSources[0], root)), cssLink);
                }
                else
                {
                    var htmlList = new List <string>();
                    foreach (var exampleSrc in Project.ExampleSources)
                    {
                        var moduleNameWOExt = PathUtils.WithoutExtension(PathUtils.Subtract(exampleSrc, root));
                        BuildFastBundlerIndexHtml(moduleNameWOExt, cssLink);
                        var justName = PathUtils.SplitDirAndFile(moduleNameWOExt).Item2;
                        FilesContent[justName + ".html"] = _indexHtml;
                        htmlList.Add(justName);
                    }

                    BuildExampleListHtml(htmlList, cssLink);
                }
            }
            else if (testProj)
            {
                BuildFastBundlerTestHtml(Project.TestSources, root, cssLink);
            }
            else if (!Project.NoHtml)
            {
                BuildFastBundlerIndexHtml(PathUtils.WithoutExtension(PathUtils.Subtract(Project.MainFile, root)),
                                          cssLink);
            }

            if (testProj)
            {
                FilesContent["test.html"] = _indexHtml;
                FilesContent[_versionDirPrefix + "jasmine-core.js"] = _tools.JasmineCoreJs;
                FilesContent[_versionDirPrefix + "jasmine-boot.js"] = _tools.JasmineBootJs;
                FilesContent[_versionDirPrefix + "loader.js"]       = _tools.LoaderJs;
            }
            else if (!Project.NoHtml)
            {
                FilesContent["index.html"] = _indexHtml;
                FilesContent[_versionDirPrefix + "loader.js"] = _tools.LoaderJs;
                if (Project.LiveReloadEnabled)
                {
                    FilesContent[_versionDirPrefix + "liveReload.js"] =
                        _tools.LiveReloadJs.Replace("##Idx##", (Project.LiveReloadIdx + 1).ToString());
                }
            }

            FilesContent[_versionDirPrefix + PathUtils.WithoutExtension(mapUrl)] = _bundleJs;
            FilesContent[_versionDirPrefix + mapUrl] = _sourceMapString;
            BuildResult.SourceMap = _sourceMap;
        }
Пример #21
0
        public void Build(string sourceRoot, bool testProj = false)
        {
            _versionDirPrefix = "";
            if (Project.OutputSubDir != null)
            {
                _versionDirPrefix = Project.OutputSubDir + "/";
            }
            var root             = Project.CommonSourceDirectory;
            var incremental      = BuildResult.Incremental;
            var start            = DateTime.UtcNow;
            var sourceMapBuilder = new SourceMapBuilder();

            if (Project.Localize)
            {
                if (!incremental)
                {
                    sourceMapBuilder.AddText(
                        $"function g11nPath(s){{return\"./{(Project.OutputSubDir != null ? (Project.OutputSubDir + "/") : "")}\"+s.toLowerCase()+\".js\"}};");
                    if (Project.DefaultLanguage != null)
                    {
                        sourceMapBuilder.AddText($"var g11nLoc=\"{Project.DefaultLanguage}\";");
                    }
                }
            }

            if (_bundlePng != null && !incremental)
            {
                sourceMapBuilder.AddText(GetInitSpriteCode());
            }

            if (!incremental)
            {
                sourceMapBuilder.AddText(_tools.LoaderJs);
                if (Project.Defines != null)
                {
                    sourceMapBuilder.AddText(GetGlobalDefines());
                }
                sourceMapBuilder.AddText(GetModuleMap());
                sourceMapBuilder.AddText(_tools.TsLibSource);
            }

            var cssLink = "";

            var sortedResultSet = incremental ? BuildResult.RecompiledIncrementaly.OrderBy(f => f.Owner.FullPath).ToArray() : BuildResult.Path2FileInfo.Values.OrderBy(f => f.Owner.FullPath).ToArray();

            if (!incremental)
            {
                foreach (var source in BuildResult.JavaScriptAssets)
                {
                    sourceMapBuilder.AddSource(source.Output, source.MapLink);
                }
            }

            foreach (var source in sortedResultSet)
            {
                if (source.Type == FileCompilationType.TypeScript ||
                    source.Type == FileCompilationType.EsmJavaScript ||
                    source.Type == FileCompilationType.JavaScript)
                {
                    if (source.Output == null)
                    {
                        continue; // Skip d.ts
                    }
                    sourceMapBuilder.AddText(
                        $"R('{PathUtils.Subtract(PathUtils.WithoutExtension(source.Owner.FullPath), root)}',function(require, module, exports, global){{");
                    var adder          = sourceMapBuilder.CreateSourceAdder(source.Output, source.MapLink);
                    var sourceReplacer = new SourceReplacer();
                    Project.ApplySourceInfo(sourceReplacer, source.SourceInfo, BuildResult);
                    sourceReplacer.Apply(adder);
                    //sourceMapBuilder.AddSource(source.Output, source.MapLink);
                    sourceMapBuilder.AddText("\n});");
                }
                else if (source.Type == FileCompilationType.Json)
                {
                    sourceMapBuilder.AddText(
                        $"R('{PathUtils.Subtract(source.Owner.FullPath, root)}',");
                    sourceMapBuilder.AddText(source.Owner.Utf8Content);
                    sourceMapBuilder.AddText(");");
                }
                else if (source.Type == FileCompilationType.ImportedCss)
                {
                    sourceMapBuilder.AddText(
                        $"R('{PathUtils.Subtract(source.Owner.FullPath, root)}',function(){{}});");
                    string cssPath = BuildResult.ToOutputUrl(source);
                    FilesContent.GetOrAddValueRef(cssPath) = source.Output;
                    cssLink += "<link rel=\"stylesheet\" href=\"" + cssPath + "\">";
                }
                else if (source.Type == FileCompilationType.Css)
                {
                    string cssPath = BuildResult.ToOutputUrl(source);
                    FilesContent.GetOrAddValueRef(cssPath) = source.Output;
                    cssLink += "<link rel=\"stylesheet\" href=\"" + cssPath + "\">";
                }
                else if (source.Type == FileCompilationType.Resource)
                {
                    FilesContent.GetOrAddValueRef(BuildResult.ToOutputUrl(source)) = source.Owner.ByteContent;
                }
            }

            if (Project.SpriteGeneration)
            {
                _bundlePng = Project.BundlePngUrl;
                var bundlePngContent = Project.SpriteGenerator.BuildImage(false);
                if (bundlePngContent != null)
                {
                    _bundlePngInfo = new List <float>();
                    foreach (var slice in bundlePngContent)
                    {
                        FilesContent.GetOrAddValueRef(PathUtils.InjectQuality(_bundlePng, slice.Quality)) = slice.Content;
                        _bundlePngInfo.Add(slice.Quality);
                    }
                }
                else
                {
                    _bundlePng = null;
                }
            }

            if (!testProj && Project.NoHtml)
            {
                sourceMapBuilder.AddText(RequireBobril());
                sourceMapBuilder.AddText(
                    $"R.r('{PathUtils.WithoutExtension(PathUtils.Subtract(Project.MainFile, root))}');");
            }

            if (Project.Localize)
            {
                Project.TranslationDb.BuildTranslationJs(_tools, FilesContent, Project.OutputSubDir);
            }

            if (incremental)
            {
                sourceMapBuilder.AddText("//# sourceMappingURL=bundle2.js.map");
                _sourceMap2       = sourceMapBuilder.Build(root, sourceRoot);
                _sourceMap2String = _sourceMap2.ToString();
                _bundle2Js        = sourceMapBuilder.Content();
                Project.Owner.Logger.Info("JS Bundle length: " + _bundleJs.Length + " SourceMap length: " + _sourceMapString.Length + " Delta: " + _bundle2Js.Length + " SM:" + _sourceMap2String.Length + " T:" + (DateTime.UtcNow - start).TotalMilliseconds.ToString("F0") + "ms");
            }
            else
            {
                sourceMapBuilder.AddText("//# sourceMappingURL=bundle.js.map");
                _sourceMap        = sourceMapBuilder.Build(root, sourceRoot);
                _sourceMapString  = _sourceMap.ToString();
                _bundleJs         = sourceMapBuilder.Content();
                _sourceMap2       = null;
                _sourceMap2String = null;
                _bundle2Js        = null;
                _cssLink          = cssLink;
                Project.Owner.Logger.Info("JS Bundle length: " + _bundleJs.Length + " SourceMap length: " + _sourceMapString.Length + " T:" + (DateTime.UtcNow - start).TotalMilliseconds.ToString("F0") + "ms");
            }
            FilesContent.GetOrAddValueRef(_versionDirPrefix + "bundle.js")     = _bundleJs;
            FilesContent.GetOrAddValueRef(_versionDirPrefix + "bundle.js.map") = _sourceMapString;
            if (incremental)
            {
                FilesContent.GetOrAddValueRef(_versionDirPrefix + "bundle2.js")     = _bundle2Js;
                FilesContent.GetOrAddValueRef(_versionDirPrefix + "bundle2.js.map") = _sourceMap2String;
                SourceMaps = new Dictionary <string, SourceMap>
                {
                    { "bundle.js", _sourceMap },
                    { "bundle2.js", _sourceMap2 }
                };
            }
            else
            {
                SourceMaps = new Dictionary <string, SourceMap>
                {
                    { "bundle.js", _sourceMap }
                };
            }
        }