From 80c1c740fbac42abcf23b39ed3b3832fbd80180f Mon Sep 17 00:00:00 2001 From: Stephen Mathieson Date: Wed, 9 Jan 2019 11:03:15 -0500 Subject: [PATCH] perf: defer rules rather than checks (#1308) This patch removes `setTimeout()` call from `Check#run()` and adds it to `Rule#run()`. The `setTimeout()` was originally added in 4657dc5d8246c1d211532e70be95043b25767e28 in order to prevent browsers from "freezing up" while running 1000s of synchronous checks. This had the downside of creating ~10k timers which slows down `axe.run()` considerably. Moving the `setTimeout()` to `Rule#run()` ensures we continue to run asynchronously to prevent "unresponsive script" warnings, but we defer as little as possible. With this patch, we should see ~40 timers created rather than 10k+ since we now create one per Rule rather than one per Check. Hat tip to @paulirish for starting this conversation in #1172. ## Reviewer checks **Required fields, to be filled out by PR reviewer(s)** - [x] Follows the commit message policy, appropriate for next version - [x] Has documentation updated, a DU ticket, or requires no documentation change - [x] Includes new tests, or was unnecessary - [x] Code is reviewed for security by: @WilcoFiers --- lib/core/base/check.js | 4 +--- lib/core/base/rule.js | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/core/base/check.js b/lib/core/base/check.js index 99a3eeac5b..7ef4001038 100644 --- a/lib/core/base/check.js +++ b/lib/core/base/check.js @@ -90,9 +90,7 @@ Check.prototype.run = function(node, options, context, resolve, reject) { if (!checkHelper.isAsync) { checkResult.result = result; - setTimeout(function() { - resolve(checkResult); - }, 0); + resolve(checkResult); } } else { resolve(null); diff --git a/lib/core/base/rule.js b/lib/core/base/rule.js index 87fcdec704..98fc223aef 100644 --- a/lib/core/base/rule.js +++ b/lib/core/base/rule.js @@ -207,6 +207,10 @@ Rule.prototype.run = function(context, options, resolve, reject) { }); }); + // Defer the rule's execution to prevent "unresponsive script" warnings. + // See https://github.com/dequelabs/axe-core/pull/1172 for discussion and details. + q.defer(resolve => setTimeout(resolve, 0)); + if (options.performanceTimer) { axe.utils.performanceTimer.mark(markEnd); axe.utils.performanceTimer.measure(