Taritsyn/BundleTransformer

Strict-mode does not work for Microsoft Ajax Js Minifier?

ZNS opened this issue · 10 comments

ZNS commented

Hi.

I'm running the latest versions of bundletransformer (1.9.171) with microsoft ajax minifier (1.9.160) with the following config:

  <bundleTransformer xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
    <core>
      <css defaultMinifier="MicrosoftAjaxCssMinifier">
        <translators>
          <add name="NullTranslator" type="BundleTransformer.Core.Translators.NullTranslator, BundleTransformer.Core" enabled="false" />
          <add name="LessTranslator" type="BundleTransformer.Less.Translators.LessTranslator, BundleTransformer.Less" />
        </translators>
        <postProcessors>
          <add name="UrlRewritingCssPostProcessor" type="BundleTransformer.Core.PostProcessors.UrlRewritingCssPostProcessor, BundleTransformer.Core" useInDebugMode="false" />
        </postProcessors>
        <minifiers>
          <add name="NullMinifier" type="BundleTransformer.Core.Minifiers.NullMinifier, BundleTransformer.Core" />
          <add name="MicrosoftAjaxCssMinifier" type="BundleTransformer.MicrosoftAjax.Minifiers.MicrosoftAjaxCssMinifier, BundleTransformer.MicrosoftAjax" />
        </minifiers>
        <fileExtensions>
          <add fileExtension=".css" assetTypeCode="Css" />
          <add fileExtension=".less" assetTypeCode="Less" />
        </fileExtensions>
      </css>
      <js defaultMinifier="MicrosoftAjaxJsMinifier">
        <translators>
          <add name="NullTranslator" type="BundleTransformer.Core.Translators.NullTranslator, BundleTransformer.Core" enabled="false" />
        </translators>
        <minifiers>
          <add name="NullMinifier" type="BundleTransformer.Core.Minifiers.NullMinifier, BundleTransformer.Core" />
          <add name="MicrosoftAjaxJsMinifier" type="BundleTransformer.MicrosoftAjax.Minifiers.MicrosoftAjaxJsMinifier, BundleTransformer.MicrosoftAjax" />
        </minifiers>
        <fileExtensions>
          <add fileExtension=".js" assetTypeCode="JavaScript" />
        </fileExtensions>
      </js>
    </core>
    <less useNativeMinification="false" ieCompat="true" strictMath="false" strictUnits="false" dumpLineNumbers="None" javascriptEnabled="true" globalVariables="" modifyVariables="">
      <jsEngine name="MsieJsEngine" />
    </less>
    <microsoftAjax>
      <js strictMode="false" />
    </microsoftAjax>
  </bundleTransformer>

and I get an exception: "Message: Strict-mode does not allow assignment to undefined variables".

   BundleTransformer.MicrosoftAjax.Minifiers.MicrosoftAjaxJsMinifier.InnerMinify(IAsset asset, JSParser jsParser) +822
   BundleTransformer.MicrosoftAjax.Minifiers.MicrosoftAjaxJsMinifier.Minify(IList`1 assets) +342
   BundleTransformer.Core.Transformers.TransformerBase.Minify(IList`1 assets) +23
   BundleTransformer.Core.Transformers.TransformerBase.Transform(IList`1 assets, BundleContext bundleContext, BundleResponse bundleResponse, VirtualPathProvider virtualPathProvider, Boolean isDebugMode) +223
   BundleTransformer.Core.Transformers.TransformerBase.Process(BundleContext bundleContext, BundleResponse bundleResponse, Boolean isDebugMode) +540
   System.Web.Optimization.Bundle.ApplyTransforms(BundleContext context, String bundleContent, IEnumerable`1 bundleFiles) +306
   System.Web.Optimization.Bundle.GetBundleResponse(BundleContext context) +59

even though I've set strictMode="false" in the config.

ZNS commented

Ok, I noted that if "use strict" is defined in the files it overrides the config setting. However it did complain on files which did not have "use strict". However there were files in the same bundle which had "use strict" defined.

Hello!

Give an example of full error message.

ZNS commented
Message: Strict-mode does not allow assignment to undefined variables: _drawers
Error code: JS1300
Severity: 0
Subcategory: run-time
File: /Content/Core/Js/Directives/Accordion.js
Start line: 9
Start column: 13
End line: 9
End column: 21

[MicrosoftAjaxParsingException: Message: Strict-mode does not allow assignment to undefined variables: _drawers
Error code: JS1300
Severity: 0
Subcategory: run-time
File: /Content/Core/Js/Directives/Accordion.js
Start line: 9
Start column: 13
End line: 9
End column: 21]
   BundleTransformer.MicrosoftAjax.Minifiers.MicrosoftAjaxJsMinifier.ParserErrorHandler(Object source, ContextErrorEventArgs args) +83
   Microsoft.Ajax.Utilities.JSParser.OnCompilerError(ContextError se) +122
   Microsoft.Ajax.Utilities.Context.HandleError(JSError errorId, Boolean forceToError) +392
   Microsoft.Ajax.Utilities.AnalyzeNodeVisitor.Visit(Block node) +857
   Microsoft.Ajax.Utilities.AnalyzeNodeVisitor.Visit(FunctionObject node) +1459
   Microsoft.Ajax.Utilities.FunctionObject.Accept(IVisitor visitor) +33
   Microsoft.Ajax.Utilities.TreeVisitor.Visit(ObjectLiteralProperty node) +61
   Microsoft.Ajax.Utilities.AnalyzeNodeVisitor.Visit(ObjectLiteralProperty node) +23
   Microsoft.Ajax.Utilities.ObjectLiteralProperty.Accept(IVisitor visitor) +33
   Microsoft.Ajax.Utilities.TreeVisitor.Visit(AstNodeList node) +94
   Microsoft.Ajax.Utilities.TreeVisitor.Visit(ObjectLiteral node) +41
   Microsoft.Ajax.Utilities.AnalyzeNodeVisitor.Visit(ObjectLiteral node) +34
   Microsoft.Ajax.Utilities.ObjectLiteral.Accept(IVisitor visitor) +33
   Microsoft.Ajax.Utilities.AnalyzeNodeVisitor.Visit(ReturnNode node) +119
   Microsoft.Ajax.Utilities.ReturnNode.Accept(IVisitor visitor) +33
   Microsoft.Ajax.Utilities.AnalyzeNodeVisitor.Visit(Block node) +857
   Microsoft.Ajax.Utilities.AnalyzeNodeVisitor.Visit(FunctionObject node) +1459
   Microsoft.Ajax.Utilities.FunctionObject.Accept(IVisitor visitor) +33
   Microsoft.Ajax.Utilities.TreeVisitor.Visit(AstNodeList node) +94
   Microsoft.Ajax.Utilities.TreeVisitor.Visit(ArrayLiteral node) +41
   Microsoft.Ajax.Utilities.ArrayLiteral.Accept(IVisitor visitor) +33
   Microsoft.Ajax.Utilities.TreeVisitor.Visit(AstNodeList node) +94
   Microsoft.Ajax.Utilities.TreeVisitor.Visit(CallNode node) +54
   Microsoft.Ajax.Utilities.AnalyzeNodeVisitor.Visit(CallNode node) +2765
   Microsoft.Ajax.Utilities.CallNode.Accept(IVisitor visitor) +33
   Microsoft.Ajax.Utilities.AnalyzeNodeVisitor.Visit(Block node) +857
   Microsoft.Ajax.Utilities.JSParser.InternalParse() +2689
   BundleTransformer.MicrosoftAjax.Minifiers.MicrosoftAjaxJsMinifier.InnerMinify(IAsset asset, JSParser jsParser) +345

[AssetMinificationException: During minification of JS code, readed from the file '/Content/Core/Js/Directives/Accordion.js', by Microsoft Ajax JS minifier syntax error has occurred. 
See more details:

Message: Strict-mode does not allow assignment to undefined variables: _drawers
Error code: JS1300
Severity: 0
Subcategory: run-time
File: /Content/Core/Js/Directives/Accordion.js
Start line: 9
Start column: 13
End line: 9
End column: 21]
   BundleTransformer.MicrosoftAjax.Minifiers.MicrosoftAjaxJsMinifier.InnerMinify(IAsset asset, JSParser jsParser) +822
   BundleTransformer.MicrosoftAjax.Minifiers.MicrosoftAjaxJsMinifier.Minify(IList`1 assets) +342
   BundleTransformer.Core.Transformers.TransformerBase.Minify(IList`1 assets) +23
   BundleTransformer.Core.Transformers.TransformerBase.Transform(IList`1 assets, BundleContext bundleContext, BundleResponse bundleResponse, VirtualPathProvider virtualPathProvider, Boolean isDebugMode) +223
   BundleTransformer.Core.Transformers.TransformerBase.Process(BundleContext bundleContext, BundleResponse bundleResponse, Boolean isDebugMode) +540
   System.Web.Optimization.Bundle.ApplyTransforms(BundleContext context, String bundleContent, IEnumerable`1 bundleFiles) +306
   System.Web.Optimization.Bundle.GetBundleResponse(BundleContext context) +59
   System.Web.Optimization.BundleResolver.GetBundleContents(String virtualPath) +213
   System.Web.Optimization.AssetManager.EliminateDuplicatesAndResolveUrls(IEnumerable`1 refs) +451
   System.Web.Optimization.AssetManager.RenderExplicit(String tagFormat, String[] paths) +34
   ASP._Page_Views_Shared_Layouts_default__Main_cshtml.Execute() in d:\Jobb\Projekt\VTO\VTO.Web\Views\Shared\Layouts\Default\_Main.cshtml:60
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +252
   System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +148
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +122
   System.Web.WebPages.<>c__DisplayClass3.<RenderPageCore>b__2(TextWriter writer) +309
   System.Web.WebPages.WebPageBase.Write(HelperResult result) +108
   System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action`1 body) +89
   System.Web.WebPages.WebPageBase.PopContext() +310
   Umbraco.Core.Profiling.ProfilingView.Render(ViewContext viewContext, TextWriter writer) +194
   System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +375
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +88
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +776
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +776
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +776
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +776
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +81
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +185
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +38
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +52
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +43
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +38
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +393
   System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +195
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +128

This error occurs at the level of Microsoft Ajax Minifier, and the Bundle Transformer is not relevant.

I can only recommend you to make the following setting in the Web.config file:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  …
  <bundleTransformer xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
    …
    <microsoftAjax>
      …
      <jsignoreErrorList="JS1300" … />
    </microsoftAjax>
    …
  </bundleTransformer>
  …
</configuration>
ZNS commented

Thanks that's good enough for me. However I did notice something now when I checked the minified source. "use strict"; is added before each file output.

...
"use strict";VTO.app.filter("capitalize",[function(){return function(n){return n&&n.length>0?n.charAt(0).toUpperCase()+n.slice(1):""}}]);
"use strict";VTO.app.filter("truncate",[function(){return function(n,t,i){return!n||n==null||n.length==0?n:i&&n.length>t?n.substr(0,t-3)+"...":n}}]);
"use strict";VTO.app.filter("to_trusted",["$sce",function(n){return function(t){return n.trustAsHtml(t)}}]);
...

Note the "use strict" above is not from the files, it's inserted during rendering I guess? Here's the "VTO.app.filter('truncate')" file for example:

VTO.app.filter('truncate', [function () {
    return function (value, length, enabled) {
        if (!value || value == null || value.length == 0)
            return value;

        if (enabled) {
            if (value.length > length) {
                return value.substr(0, length - 3) + "...";
            }
        }

        return value;
    };
}]);

You have installed the BundleTransformer.ConfigurationIntelliSense package?

"use strict"; is added before each file output.

You can try the following settings:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  …
  <bundleTransformer xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
    …
    <core …>
      <csscombineFilesBeforeMinification="true">
        …
      </css>
      <jscombineFilesBeforeMinification="true">
        …
      </js>
      …
    </core>
    …
  </bundleTransformer>
  …
</configuration>
ZNS commented

I have not installed that package but thanks for the tip. If I combine before minification I get other errors, which is not that unexpected. But I wonder why "use strict" is inserted that way during render? I'm thinking it's something in one of the files that causes it. Because in our production environment "use strict" is not inserted.

You can compare outputs here: https://gist.github.com/ZNS/d384eac321525e1247525eab41b391da

If I combine before minification I get other errors, which is not that unexpected.

Try to determine what caused these errors.

But I wonder why "use strict" is inserted that way during render? I'm thinking it's something in one of the files that causes it.

Everything is very simple. By default, the Bundle Transformer processes each file separately, and the Microsoft Ajax Minifier adds the "use strict" directive to beginning of each file. I suggest you use only one setting:

…
<jsignoreErrorList="JS1300" strictMode="false" … />
…
ZNS commented

Everything is very simple. By default, the Bundle Transformer processes each file separately, and the Microsoft Ajax Minifier adds the "use strict" directive to beginning of each file.

Ok, but that must have changed in some late version of Microsoft Ajax Minifier then? Since we don't have this in production which runs BundleTransformer.MicrosoftAjax 1.9.92

In fact, nothing changes in the BundleTransformer.MicrosoftAjax module since version 1.9.43 (after the Microsoft Ajax Minifier project was closed).

Maybe something has changed in your scripts? The easiest way to test this is to roll back to version 1.9.92.