Problem/Motivation

We are having problems with Peast not being able to parse some of the JavaScripts generated by our theme build pipeline, causing aggregation to fail with a parsing exception (...and it's fairly slow for large files when it doesn't) in Drupal\Core\Asset\JsOptimizer.

Steps to reproduce

Aggregate any JS file which has a class with a method named `async`. See https://github.com/mck89/peast/issues/62 for a minimal example.
In our case, the file containing the class is generated by our theme building pipeline and part of the clientside runtime, so not something we can easily change.
An exception is thrown with just the parsing error message (no source file name or parsing position included) and the aggregation is aborted.

Note that if I hack around this and rename all the async methods in the file it parses correctly, but I would be hesitant to assume Peast won't choke on something else later - given build pipelines and JavaScript itself are constantly changing.

Proposed resolution

Wrap the calls to Peast in a try-catch and if the parsing or rendering fails, log the error and include the unprocessed file as before Peast was introduced.
If there was an actual JavaScript syntax error it would then be possible for a developer to more easily identify it as part of the aggregated file

Remaining tasks

Implement a fix.

User interface changes

None

API changes

None

Data model changes

None

Release notes snippet

Issue fork drupal-3381097

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

TwoD created an issue. See original summary.

twod’s picture

Status: Active » Needs work

Whoops, meant to create this for 11.x, but no matter, they seem to be identical.

Pushed up a simple proof of concept which catches the exception, creates an informative log entry if it can, and proceeds to use the original source to not cause a complete crash.

Other than it also needing a test, Is this a good approach?

b_sharpe’s picture

THANK YOU for this. I was running down a big rabbit hole when JS aggregation was on trying to find out what was causing my errors and this saved me.

catch’s picture

Good idea - can you open an MR for the branch?

To test this - do we need js with a syntax exception that Peast will definitely throw an exception for?

catch’s picture

I opened #3382123: Update Peast to 1.15.4 to update Peast too.

nicxvan’s picture

This seems to also resolve the case where you mistakenly don't mark a library as minified: https://www.drupal.org/project/drupal/issues/3371010

b_sharpe’s picture

Status: Needs work » Needs review

Rebased and Fixed issues with tests failing. Needs Review

catch’s picture

Status: Needs review » Needs work

Couple of comments on the MR but overall looking good.

b_sharpe’s picture

Status: Needs work » Needs review

Went with the default system logger as there isn't any other instances of asset logging to really warrant it's own channel.

catch’s picture

Status: Needs review » Reviewed & tested by the community

Looks great. Will mean that actually broken JavaScript won't cause any more problems than it would have done in 10.x, and if Peast has its own parsing errors on unusual/new syntax that we still get a perfectly usable aggregate, just without that particular file minimized.

twod’s picture

Lol, was just about to check in on this and it's already RTBC.

Do we need an actual test to ensure broken scripts keep making it through to the aggregated files (or at least go through this part unmodified)?

catch’s picture

Version: 10.1.x-dev » 11.x-dev
Status: Reviewed & tested by the community » Needs work
StatusFileSize
new1.7 KB

Good point yes we do.

Here's a test only patch that should fail.

catch’s picture

Status: Needs work » Needs review
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new90 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

catch’s picture

Status: Needs work » Needs review
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new90 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

catch’s picture

Status: Needs work » Needs review

Rebased/retargeted onto 11.x

b_sharpe’s picture

Status: Needs review » Reviewed & tested by the community

Looks good!

  • catch committed 06264047 on 10.1.x
    Issue #3381097 by catch, b_sharpe, TwoD: Need to catch Peast exceptions...

  • catch committed cb606a0c on 11.x
    Issue #3381097 by catch, b_sharpe, TwoD: Need to catch Peast exceptions
    
catch’s picture

Status: Reviewed & tested by the community » Fixed

Here's the interdiff of the test coverage I added:

diff --git a/core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php b/core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php
index 15f21a22cf0062f0e16a860257e069ab8c6b0e10..3c4623ab228fdb1c3df9573a041dce6b8a046296 100644
--- a/core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/JsOptimizerUnitTest.php
@@ -119,6 +119,16 @@ public function providerTestOptimize() {
         ],
         file_get_contents($path . 'to_be_minified.js.optimized.js'),
       ],
+      4 => [
+        [
+          'type' => 'file',
+          'preprocess' => TRUE,
+          'data' => $path . 'syntax_error.js',
+        ],
+        // When there is a syntax error, the 'optimized' contents are the
+        // contents of the original file.
+        file_get_contents($path . 'syntax_error.js'),
+      ],
     ];
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Asset/js_test_files/syntax_error.js b/core/tests/Drupal/Tests/Core/Asset/js_test_files/syntax_error.js
new file mode 100644
index 0000000000000000000000000000000000000000..3794c41c8451c98cfcbbaba6b6839263f3aeebbc
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Asset/js_test_files/syntax_error.js
@@ -0,0 +1,13 @@
+/**
+ * Some comments.
+ */
+
+(function foo() {
+  // Missing closing parenthesis.
+  if (true {
+    'print 1';
+  }
+  else {
+    'print 2';
+  }
+})

Given that was the only code I touched here, I'm going to go ahead and commit it. Committed/pushed to 11.x and cherry-picked to 10.1.x, thanks!

catch’s picture

Version: 11.x-dev » 10.1.x-dev

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.