Endless JS loop if there's an uncaught exception in an ajax block

Bug #1544424 reported by Aaron Wells on 2016-02-11
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Mahara
Medium
Aaron Wells
15.10
Medium
Aaron Wells

Bug Description

I noticed this one via Bug 1544381. If there is a Dwoo error in one of the blocks rendered via Ajax, then it causes an endless loop of Javascript. To the end user, the appearance is that the title bar of the page keeps flashing, and the browser slows down somewhat.

What's happening is this:

1. The initial call to view.php tries to render every block.
2. For the ajax blocks instead of calling "render_instance()", it returns a placeholder with some data attributes that identify it as an ajax block placeholder, and indicate which block instance to load there.
3. view.php's template loads up "head.tpl", which is hard-coded to include "block.js", the Javascript file with the code to load the AJAX blocks.
4. block.js, once it's loaded, executes some code that finds every one of those ajax block placeholders, executes "blocktype.ajax.php?block_instance=X" for each one, and then takes the return value from that request and pops it into the page, also triggering any Javascript that is loaded in that return value.
5. blocktype.ajax.php calls render_instance() on the block instance that has been passed to it.
6. If render_instance() triggers an uncaught MaharaException, then it gets handled by the MaharaException->handle_exception() method, which loads up error.tpl in order to display a nice error page with the standard headers and footers.
7. error.tpl includes head.tpl, which then includes "block.js" again.
8. block.js again locates every AJAX block and calls blocktype.ajax.php and loads its content again. It scans the whole page, which mean it notices and re-executes for the AJAX blocks from the initial view.php call!
9. The block errors out again.
10. The new error again loads error.tpl
11. error.tpl again includes block.js
12. block.js again locates every AJAX block...

This problem is present in 15.10+. It was caused during the Bootstrapification, when we rewrote the ajax block code to remove the executable code from each block and put it all into block.js. The simplest solution is probably just to make sure that block.js only gets included in pages where it is actually needed. (Also, possibly, to put a check into block.js to make sure it only gets executed *once* per pageload, even if it is loaded multiple times. Perhaps using a Javascript variable in global scope.

Aaron Wells (u-aaronw) on 2016-02-11
tags: added: ajax bootstrap javascript regression
Mahara Bot (dev-mahara) wrote :

Patch for "master" branch: https://reviews.mahara.org/6054

Aaron Wells (u-aaronw) wrote :

Replicating this requires causing an error in one of the ajax block's render_instance methods. You can either replicate Bug 1544381, or you can directly edit a block file like so:

1. Open up file htdocs/blocktype/newviews/lib.php
2. Locate the function "render_instance()" on line 32.
3. Inside that function, put an exception, like so:

    public static function render_instance(BlockInstance $instance, $editing=false) {
        global $USER;

        // here's an exception
        throw new Exception('die.');

        require_once('view.php');
        $configdata = $instance->get('configdata');
        $nviews = isset($configdata['limit']) ? intval($configdata['limit']) : 5;

4. Log in to Mahara and view your dashboard (which should contain a new views block as per the default)

Expected result: The new views block loads via Ajax
Actual result: The page blinks and reloads infinitely.

Reviewed: https://reviews.mahara.org/6054
Committed: https://git.mahara.org/mahara/mahara/commit/172d0e9516d887e8c39a2623ebf983e5a7a1ee74
Submitter: Robert Lyon (<email address hidden>)
Branch: master

commit 172d0e9516d887e8c39a2623ebf983e5a7a1ee74
Author: Aaron Wells <email address hidden>
Date: Thu Feb 11 18:32:35 2016 +1300

Bug 1544424: Only load block.js when it's actually needed

This prevents an infinite loop caused by an error in a ajax block
causing error.tpl to be rendered, which causes block.js to get loaded,
which causes a new ajax request for all the ajax blocks, which causes
error.tpl to be rendered, etc.

Also moving this JS file out of the theme directory and into the /js
directory, because it's core, not theme.

behatnotneeded: Can't test error state via Behat

Change-Id: Idc83002dbf5cb8af36d9d33e916da2bdfa5a308f

Reviewed: https://reviews.mahara.org/6088
Committed: https://git.mahara.org/mahara/mahara/commit/405f17099f4fc925c73137e615c5ca8d9cbc2015
Submitter: Robert Lyon (<email address hidden>)
Branch: 15.10_STABLE

commit 405f17099f4fc925c73137e615c5ca8d9cbc2015
Author: Aaron Wells <email address hidden>
Date: Thu Feb 11 18:32:35 2016 +1300

Bug 1544424: Only load block.js when it's actually needed

This prevents an infinite loop caused by an error in a ajax block
causing error.tpl to be rendered, which causes block.js to get loaded,
which causes a new ajax request for all the ajax blocks, which causes
error.tpl to be rendered, etc.

Also moving this JS file out of the theme directory and into the /js
directory, because it's core, not theme.

behatnotneeded: Can't test error state via Behat

Change-Id: Idc83002dbf5cb8af36d9d33e916da2bdfa5a308f
(cherry picked from commit 172d0e9516d887e8c39a2623ebf983e5a7a1ee74)

no longer affects: mahara/16.04
Changed in mahara:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers