diff --git a/core/misc/drupal.js b/core/misc/drupal.js index 458d385..f49aef0 100644 --- a/core/misc/drupal.js +++ b/core/misc/drupal.js @@ -17,27 +17,7 @@ if (window.jQuery) { "use strict"; - /** - * Custom error type thrown after attach/detach if one or more behaviors failed. - * - * @param list - * An array of errors thrown during attach/detach. - * @param event - * A string containing either 'attach' or 'detach'. - */ - function DrupalBehaviorError(list, event) { - this.name = 'DrupalBehaviorError'; - this.event = event || 'attach'; - this.list = list; - // Makes the list of errors readable. - var messageList = []; - messageList.push(this.event); - for (var i = 0, il = this.list.length; i < il; i++) { - messageList.push(this.list[i].behavior + ': ' + this.list[i].error.message); - } - this.message = messageList.join(' ; '); - } - DrupalBehaviorError.prototype = new Error(); + var behaviors_done = []; /** * Attach all registered behaviors to a page element. @@ -80,23 +60,34 @@ if (window.jQuery) { Drupal.attachBehaviors = function (context, settings) { context = context || document; settings = settings || drupalSettings; - var i, errors = [], behaviors = Drupal.behaviors; + var i, errorThrown, behaviors = Drupal.behaviors; // Execute all of them. for (i in behaviors) { - if (behaviors.hasOwnProperty(i) && typeof behaviors[i].attach === 'function') { - // Don't stop the execution of behaviors in case of an error. + if (behaviors.hasOwnProperty(i) && typeof behaviors[i].attach === 'function' && behaviors_done.indexOf(i) === -1) { + // Catching errors makes debugging more difficult, so we start with + // errorThrown set to true before setting it to false after calling + // the behavior -- if it's still set to true in the finally block, it + // means the behavior threw. + errorThrown = true; try { behaviors[i].attach(context, settings); - } - catch (e) { - errors.push({ behavior: i, error: e }); + errorThrown = false; + } finally { + behaviors_done.push(i); + if (errorThrown) { + // The behavior i threw an error; execute the remaining + // behaviors but silence any exceptions from them to ensure that + // the first error is the one to bubble up. + try { + Drupal.attachBehaviors(context, settings); + } catch (e) { + } + } } } } - // Once all behaviors have been processed, inform the user about errors. - if (errors.length) { - throw new DrupalBehaviorError(errors, 'attach'); - } + // reset it + behaviors_done = []; }; // Attach all behaviors.