Casperjs Bind Issue

CasperJS bind issue

The shim below isn't needed anymore if PhantomJS 2 is used. Sadly CasperJS 1.1-beta3 doesn't support it yet, so you might want to use the master branch from GitHub.


The problem is that PhantomJS v1.x does not support the Function.prototype.bind. You need to add a shim for that. In CasperJS it goes into the page.initialized event handler. This shim works well for me on instragram:

casper.on( 'page.initialized', function(){
this.evaluate(function(){
var isFunction = function(o) {
return typeof o == 'function';
};

var bind,
slice = [].slice,
proto = Function.prototype,
featureMap;

featureMap = {
'function-bind': 'bind'
};

function has(feature) {
var prop = featureMap[feature];
return isFunction(proto[prop]);
}

// check for missing features
if (!has('function-bind')) {
// adapted from Mozilla Developer Network example at
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
bind = function bind(obj) {
var args = slice.call(arguments, 1),
self = this,
nop = function() {
},
bound = function() {
return self.apply(this instanceof nop ? this : (obj || {}), args.concat(slice.call(arguments)));
};
nop.prototype = this.prototype || {}; // Firefox cries sometimes if prototype is undefined
bound.prototype = new nop();
return bound;
};
proto.bind = bind;
}
});
});

It doesn't work if the shim is exported into its own file and included through the clientScripts option, because those are appended after the instagram javascript which is too late.

What might also work is registering to page.resource.received event.

There is also the pure PhantomJS question: bind polyfill for PhantomJS

Silent errors in CasperJS

There is an open PhantomJS issue on this.

You can get around it by wrapping each then & similar with a reportErrors function, e.g.:

function reportErrors(f) {
var ret = null;
try {
ret = f();
} catch (e) {
casper.echo("ERROR: " + e);
casper.exit();
}
return ret;
}

casper.then(function() {
reportErrors(function() {
...
});
});

why isn't my casperjs displaying any errors?

You're likely using PhantomJS 2.x. It has a known bug where some errors are not reported. That includes the class of errors that you're describing.

Also, registering to the various error events of CasperJS/PhantomJS doesn't help in this case, but here they are just in case:

// http://phantomjs.org/api/phantom/handler/on-error.html
phantom.onError = function(msg, trace) {
var msgStack = ['PHANTOM ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function +')' : ''));
});
}
console.error(msgStack.join('\n'));
phantom.exit(1);
};

// http://docs.casperjs.org/en/latest/events-filters.html#remote-message
casper.on("remote.message", function(msg) {
this.echo("Console: " + msg);
});

// http://docs.casperjs.org/en/latest/events-filters.html#page-error
casper.on("page.error", function(msg, trace) {
this.echo("Error: " + msg);
// maybe make it a little fancier with the code from the PhantomJS equivalent
});

// http://docs.casperjs.org/en/latest/events-filters.html#resource-error
casper.on("resource.error", function(resourceError) {
this.echo("ResourceError: " + JSON.stringify(resourceError, undefined, 4));
});

// http://docs.casperjs.org/en/latest/events-filters.html#page-initialized
casper.on("page.initialized", function(page) {
// CasperJS doesn't provide `onResourceTimeout`, so it must be set through
// the PhantomJS means. This is only possible when the page is initialized
page.onResourceTimeout = function(request) {
console.log('Response Timeout (#' + request.id + '): ' + JSON.stringify(request));
};
});

You can run something like eslint or jshint over the script to catch syntax errors and you can run your script in PhantomJS 1.9.8/1.9.7 in order to catch these sort of errors.



Related Topics



Leave a reply



Submit