Revision: 5703
Author: [email protected]
Date: Tue Oct 21 20:54:06 2014 UTC
Log: Support top-level onerror for non-DOM guests.
https://codereview.appspot.com/157300043
r5701, which introduced a bottleneck function for window.onerror
invocations, did not consider the case of guests without DOM.
Move domicile.handleUncaughtException to be
Domado.handleUncaughtException so that it can be invoked even if
there is no domicile object.
handleUncaughtException now takes the window (or global/imports)
object as an argument, and is not otherwise changed.
Arguably it should be moved out of domado.js entirely, but I
currently think that it makes the most sense there, since onerror
is a browser feature rather than a JS feature, and we do not yet
have a "browser features other than the DOM" module. (One reason
we might gain such is if we provide setTimeout-and-friends in the
no-DOM case, which we probably should.)
[email protected]
https://code.google.com/p/google-caja/source/detail?r=5703
Modified:
/trunk/src/com/google/caja/plugin/domado.js
/trunk/src/com/google/caja/plugin/html-emitter.js
/trunk/src/com/google/caja/plugin/ses-frame-group.js
/trunk/tests/com/google/caja/plugin/test-cajajs-invocation.js
=======================================
--- /trunk/src/com/google/caja/plugin/domado.js Mon Oct 13 19:19:17 2014 UTC
+++ /trunk/src/com/google/caja/plugin/domado.js Tue Oct 21 20:54:06 2014 UTC
@@ -1294,7 +1294,7 @@
* @return A record of functions attachDocument, dispatchEvent, and
* dispatchToHandler.
*/
- return cajaVM.constFunc(function Domado_() {
+ function Domado_() {
// Everything in this scope but not in function attachDocument() below
// does not contain lexical references to a particular DOM instance,
but
// may have some kind of privileged access to Domado internals.
@@ -1420,7 +1420,7 @@
* value which would be evaluated outside the sandbox.
*/
function tameSetAndClear(target, set, clear, setName, clearName,
passArg,
- evalStrings, environment, handleUncaughtException) {
+ evalStrings, environment) {
var ids = new WeakMap();
function tameSet(action, delayMillis) {
// Existing browsers treat a timeout/interval of null or undefined
as a
@@ -1459,7 +1459,8 @@
action(); // setTimeout, setInterval
}
} catch (e) {
- handleUncaughtException(e, '<setName callback>');
+ Domado_.handleUncaughtException(
+ target, e, '<setName callback>');
}
}
var id = set(actionWrapper, delayMillis | 0);
@@ -3627,7 +3628,7 @@
try {
Function.prototype.call.call(func, thisArg, tameEventObj);
} catch (e) {
- domicile.handleUncaughtException(e,
+ Domado_.handleUncaughtException(tameWindow, e,
'<' + tameEventObj.type + ' listener>');
}
}
@@ -6714,58 +6715,6 @@
}
return null;
});
-
- /**
- * Invoke the possibly guest-supplied onerror handler due to an
uncaught
- * exception. This wrapper exists to ensure consistent behavior
among the
- * many places we need "top-level" catches.
- *
- * handleUncaughtException attempts to never throw, even if the
onerror
- * handler is not a function, stringifying the exception throws, and
so
- * on.
- *
- * Usage:
- * try {
- * ...guest callback of some sort, say an event handler...
- * } catch (e) {
- * domicile.handleUncaughtException(e, 'event handler');
- * }
- *
- * @param {Error} error
- * @param {string} context Script source URL if available, otherwise
- * a user-facing explanation of what kind of top-level handler
caught
- * this error, in angle brackets; e.g. '<event listener>' or
- * '<setTimeout>'.
- */
- domicile.handleUncaughtException =
- cajaVM.constFunc(function(error, context) {
- // This is an approximate implementation of
- //
https://html.spec.whatwg.org/multipage/webappapis.html#runtime-script-errors
- // The error event object is implicit.
- try {
- // Call with this == tameWindow; this is intended behavior.
- // Refs for arguments:
- //
https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-attributes:onerroreventhandler
- //
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers.onerror
- tameWindow.onerror(
- 'Uncaught ' + error,
- context,
- // TODO(kpreid): Once there is a standardized error stack trace
- // interface, use it to recover more error information if we
can.
- -1, // line number
- -1, // column number
- error);
- } catch (e) {
- if (typeof console !== 'undefined') {
- try {
- console.error('Error while reporting guest script error: ',
e);
- } catch (metaError) {
- console.error('Error while reporting error while reporting '
+
- 'guest script error. Sorry.');
- }
- }
- }
- });
// Taming of Styles:
@@ -7050,13 +6999,13 @@
window.setTimeout,
window.clearTimeout,
'setTimeout', 'clearTimeout',
- false, true, this, domicile.handleUncaughtException);
+ false, true, this);
tameSetAndClear(
this,
window.setInterval,
window.clearInterval,
'setInterval', 'clearInterval',
- false, true, this, domicile.handleUncaughtException);
+ false, true, this);
if (window.requestAnimationFrame) {
tameSetAndClear(
this,
@@ -7064,7 +7013,7 @@
return window.requestAnimationFrame(code); },
window.cancelAnimationFrame,
'requestAnimationFrame', 'cancelAnimationFrame',
- true, false, undefined, domicile.handleUncaughtException);
+ true, false, undefined);
}
}
inertCtor(TameWindow, Object, 'Window');
@@ -7412,7 +7361,7 @@
isUserAction, pluginId, handler,
[ node, tameEventObj ]);
} catch (ex) {
- domicile.handleUncaughtException(ex,
+ Domado_.handleUncaughtException(imports, ex,
'<' + tameEventObj.type + ' handler>');
}
}
@@ -7479,7 +7428,64 @@
plugin_dispatchToHandler: plugin_dispatchToHandler,
getDomicileForWindow: windowToDomicile.get.bind(windowToDomicile)
});
+ }
+
+ /**
+ * Invoke the possibly guest-supplied onerror handler due to an uncaught
+ * exception. This wrapper exists to ensure consistent behavior among the
+ * many places we need "top-level" catches. It is not a part of the
domicile
+ * object because it is used even in DOM-less guest environments, but is
in
+ * this file because it is a "browser" feature rather than a "JS"
feature.
+ *
+ * handleUncaughtException attempts to never throw, even if the onerror
+ * handler is not a function, stringifying the exception throws, and so
+ * on.
+ *
+ * Usage:
+ * try {
+ * ...guest callback of some sort, say an event handler...
+ * } catch (e) {
+ * handleUncaughtException(tameWindow, e, 'event handler');
+ * }
+ *
+ * @param {Object} globalObj Object on which to find the onerror handler.
+ * @param {Error} error
+ * @param {string} context Script source URL if available, otherwise
+ * a user-facing explanation of what kind of top-level handler caught
+ * this error, in angle brackets; e.g. '<event listener>' or
+ * '<setTimeout>'.
+ */
+ Domado_.handleUncaughtException =
+ cajaVM.constFunc(function(globalObj, error, context) {
+ // This is an approximate implementation of
+ //
https://html.spec.whatwg.org/multipage/webappapis.html#runtime-script-errors
+ // The error event object is implicit.
+ try {
+ // Call with this == globalObj; this is intended behavior.
+ // Refs for arguments:
+ //
https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-attributes:onerroreventhandler
+ //
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers.onerror
+ globalObj.onerror(
+ 'Uncaught ' + error,
+ context,
+ // TODO(kpreid): Once there is a standardized error stack trace
+ // interface, use it to recover more error information if we can.
+ -1, // line number
+ -1, // column number
+ error);
+ } catch (e) {
+ if (typeof console !== 'undefined') {
+ try {
+ console.error('Error while reporting guest script error: ', e);
+ } catch (metaError) {
+ console.error('Error while reporting error while reporting ' +
+ 'guest script error. Sorry.');
+ }
+ }
+ }
});
+
+ return cajaVM.constFunc(Domado_);
})();
// Exports for closure compiler.
=======================================
--- /trunk/src/com/google/caja/plugin/html-emitter.js Mon Oct 13 19:19:17
2014 UTC
+++ /trunk/src/com/google/caja/plugin/html-emitter.js Tue Oct 21 20:54:06
2014 UTC
@@ -447,7 +447,7 @@
// a crypto hash
var compiledModule = compileModule(scriptInnerText,
opt_mitigate);
try {
- compiledModule(opt_domicile.window);
+ compiledModule(domicile.window);
// Success.
domicile.fireVirtualEvent(scriptNode, 'Event', 'load');
@@ -468,7 +468,12 @@
// TODO(kpreid): How should the virtual event on the node interact
with
// this handling? Should they actually be the same event and cancel
here?
- opt_domicile.handleUncaughtException(
+ //
+ // Note on window.Domado: We don't have a @requires dep here because
we
+ // can run without Domado, but we know that Domado is loaded if
we're in
+ // this code.
+ window.Domado.handleUncaughtException(
+ domicile.window,
// TODO(kpreid): should have an Error instance here, not a
string.
errorMessage,
// URL where error was raised.
=======================================
--- /trunk/src/com/google/caja/plugin/ses-frame-group.js Mon Oct 13
19:19:17 2014 UTC
+++ /trunk/src/com/google/caja/plugin/ses-frame-group.js Tue Oct 21
20:54:06 2014 UTC
@@ -282,7 +282,7 @@
try {
result = compiledFunc(imports);
} catch (e) {
- gman.domicile.handleUncaughtException(e, gman.getUrl());
+ Domado.handleUncaughtException(imports, e, gman.getUrl());
}
if (opt_runDone) {
opt_runDone(result);
=======================================
--- /trunk/tests/com/google/caja/plugin/test-cajajs-invocation.js Mon Oct
13 19:19:17 2014 UTC
+++ /trunk/tests/com/google/caja/plugin/test-cajajs-invocation.js Tue Oct
21 20:54:06 2014 UTC
@@ -92,8 +92,9 @@
}
});
- jsunitRegister('testScriptError', function testScriptError() {
- caja.load(createDiv(), uriPolicy, jsunitCallback(function(frame) {
+ function testScriptError(hasDOM) {
+ caja.load(hasDOM ? createDiv() : undefined, uriPolicy,
+ jsunitCallback(function(frame) {
var url = 'http://caja-test-error-page.invalid';
var onerrorFired = 0;
frame.code(
@@ -117,7 +118,12 @@
jsunitPass();
}));
}));
- });
+ }
+ jsunitRegister('testScriptErrorWithDom', function() {
+ testScriptError(true); });
+
+ jsunitRegister('testScriptErrorWithoutDom', function() {
+ testScriptError(false); });
jsunitRegister('testDefaultHeight', function testDefaultHeight() {
var hostPageDiv = createDiv();
--
---
You received this message because you are subscribed to the Google Groups "Google Caja Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.