sabberworm / karma-iframes

Lets you run each test in a separate context, loaded as an iframe.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

JS errors sent from the iframe to the parent context aren't serialised correctly

thomas-r7 opened this issue · comments

The callback of window.onerror is as follows:

window.onerror = function(message, source, lineno, colno, error) { ... }

The last parameter 'error' is an Error instance. When this error is caught and sent to the context (via the reverse context), postMessage is used but Error objects can't be serialised in postMessage and so the call fails and the error never makes it to the parent context. The error thrown in this case looks like:
Uncaught DOMException: Failed to execute 'postMessage' on 'Window': Error could not be cloned.

This seems to specifically be for errors in the JS document itself (syntax errors etc) rather than asserts in the tests themselves.

The offending code is in reverse-context.js, lines 30-36:

DIRECT_METHODS = ['error', 'log', 'complete', 'result'];
DIRECT_METHODS.forEach(method => {
	karma[method] = function() {
		callParentKarmaMethod(method, Array.prototype.slice.call(arguments));
	}
	karma[method].displayName = method+' (proxied)';
});

This could be corrected by adding a transform to the arguments array that converts Error objects into strings, e.g.

DIRECT_METHODS = ['error', 'log', 'complete', 'result'];
DIRECT_METHODS.forEach(method => {
	karma[method] = function() {
		var args = Array.prototype.slice.call(arguments);
		for (var i = 0, l = args.length; i < l; ++i) {
			if (args[i] instanceof Error) {
				args[i] = args[i].stack || args[i].toString();
			}
		}
		callParentKarmaMethod(method, args);
	}
	karma[method].displayName = method+' (proxied)';
});

This does mean however that karma never sees an Error object on the other end, only a string, but it gets sent right to karma.error so this might be ok.

Thanks a lot for investigating this and for the suggested fix.

I’d put the sanitization code directly in callParentKarmaMethod but otherwise I like this fix.

Maybe we could use an object that contains all the properties of the original error instead of simply using the stack or toString.

And the messageListener in iframes-adapter could then again make an error out of this object…

Could you test that for me and open a pull-request?

Released with 1.2.2