From 6f89fe04ea4797627730d9e514c49b83e4580e9d Mon Sep 17 00:00:00 2001 From: Patrick Steele-Idem Date: Wed, 12 Apr 2017 20:27:59 -0600 Subject: [PATCH] Refactored out nextTick/setImmediate for better error handling --- components/update-manager.js | 31 +++---------------------------- runtime/nextTick-browser.js | 30 ++++++++++++++++++++++++++++++ runtime/nextTick.js | 1 + runtime/package.json | 3 ++- taglibs/async/await-tag.js | 36 +++++++++++++++++++----------------- 5 files changed, 55 insertions(+), 46 deletions(-) create mode 100644 runtime/nextTick-browser.js create mode 100644 runtime/nextTick.js diff --git a/components/update-manager.js b/components/update-manager.js index 8bc1285e3..391f1e028 100644 --- a/components/update-manager.js +++ b/components/update-manager.js @@ -4,32 +4,7 @@ var updatesScheduled = false; var batchStack = []; // A stack of batched updates var unbatchedQueue = []; // Used for scheduled batched updates -var win = window; -var setImmediate = win.setImmediate; - -if (!setImmediate) { - if (win.postMessage) { - var queue = []; - var messageName = 'si'; - win.addEventListener('message', function (event) { - var source = event.source; - if (source == win || !source && event.data === messageName) { - event.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); - - setImmediate = function(fn) { - queue.push(fn); - win.postMessage(messageName, '*'); - }; - } else { - setImmediate = setTimeout; - } -} +var nextTick = require('../runtime/nextTick'); /** * This function is called when we schedule the update of "unbatched" @@ -57,7 +32,7 @@ function scheduleUpdates() { updatesScheduled = true; - setImmediate(updateUnbatchedComponents); + nextTick(updateUnbatchedComponents); } function updateComponents(queue) { @@ -129,4 +104,4 @@ function queueComponentUpdate(component) { } exports.$__queueComponentUpdate = queueComponentUpdate; -exports.$__batchUpdate = batchUpdate; \ No newline at end of file +exports.$__batchUpdate = batchUpdate; diff --git a/runtime/nextTick-browser.js b/runtime/nextTick-browser.js new file mode 100644 index 000000000..0582c87ea --- /dev/null +++ b/runtime/nextTick-browser.js @@ -0,0 +1,30 @@ +/* globals window */ + +var win = window; +var setImmediate = win.setImmediate; + +if (!setImmediate) { + if (win.postMessage) { + var queue = []; + var messageName = 'si'; + win.addEventListener('message', function (event) { + var source = event.source; + if (source == win || !source && event.data === messageName) { + event.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + setImmediate = function(fn) { + queue.push(fn); + win.postMessage(messageName, '*'); + }; + } else { + setImmediate = setTimeout; + } +} + +module.exports = setImmediate; diff --git a/runtime/nextTick.js b/runtime/nextTick.js new file mode 100644 index 000000000..51f167c98 --- /dev/null +++ b/runtime/nextTick.js @@ -0,0 +1 @@ +module.exports = process.nextTick; diff --git a/runtime/package.json b/runtime/package.json index 7614baa1b..e90efdcc0 100644 --- a/runtime/package.json +++ b/runtime/package.json @@ -1,6 +1,7 @@ { "browser": { "./loader/index.js": "./loader/index-browser.js", + "./nextTick": "./nextTick-browser.js", "./env-init.js": false } -} \ No newline at end of file +} diff --git a/taglibs/async/await-tag.js b/taglibs/async/await-tag.js index ab49c3f64..2ff3765e6 100644 --- a/taglibs/async/await-tag.js +++ b/taglibs/async/await-tag.js @@ -3,32 +3,30 @@ var logger = require('raptor-logging').logger(module); var AsyncValue = require('raptor-async/AsyncValue'); var isClientReorderSupported = require('./client-reorder').isSupported; +var nextTick = require('../../runtime/nextTick'); function isPromise(o) { return o && typeof o.then === 'function'; } +function safeRenderBody(renderBody, targetOut, data) { + try { + renderBody(targetOut, data); + } catch(err) { + return err; + } +} + function promiseToCallback(promise, callback, thisObj) { if (callback) { var finalPromise = promise .then(function(data) { - callback(null, data); + nextTick(callback.bind(this, null, data)); + }) + .then(null, function(err) { + nextTick(callback.bind(this, err)); }); - if (typeof promise.catch === 'function') { - finalPromise = finalPromise.catch(function(err) { - callback(err); - }); - } else if (typeof promise.fail === 'function') { - finalPromise = finalPromise.fail(function(err) { - callback(err); - }); - } else { - finalPromise = finalPromise.then(null, function(err) { - callback(err); - }); - } - if (finalPromise.done) { finalPromise.done(); } @@ -116,8 +114,12 @@ module.exports = function awaitTag(input, out) { } else if (renderTimeout) { renderTimeout(targetOut); } else { - if (input.renderBody) { - input.renderBody(targetOut, data); + var renderBodyFunc = input.renderBody; + if (renderBodyFunc) { + var renderBodyErr = safeRenderBody(renderBodyFunc, targetOut, data); + if (renderBodyErr) { + return renderBody(renderBodyErr); + } } }