I'm trying to execute a basic app that uses RequireJS (2.1.8), WireJS (0.10.2) and PhantomJS (1.9.2):
- When running the app using PhantomJS (this is my goal), WireJS fails to load (see error below).
- When running the app using Chrome, it completes properly.
Please help to point out the missing part for WireJS to run properly under PhantomJS.
Following are my app files.
1) app.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>SaphirJS.core</title>
<script data-main="app" src="../../../target/deps/require-0.0.1/2.1.8/require.js"> </script>
</head>
<body>
</body>
</html>
2) app.js
"use strict";
require.config({
baseUrl: ".",
packages: [
{ name: 'wire', location: '../../../target/deps/wire-0.0.1/0.10.2', main: 'wire' },
{ name: 'when', location: '../../../target/deps/when-0.0.1/2.4.1', main: 'when' },
{ name: 'meld', location: '../../../target/deps/meld-0.0.1/1.3.0', main: 'meld' }
]
});
require(["wire!wireContext"], function(wireContext) {
alert(wireContext.message);
});
3) wireContext.js
define({
message: "Hello World!"
});
4) phantom-runner.js
(function() {
'use strict';
var args = require('system').args,
timeoutRef = undefined,
timeLimit = 10000;
// arg[0]: scriptName, args[1...]: arguments
if (args.length !== 2) {
console.error('Usage:\n phantomjs runner.js [url-of-your-qunit-testsuite]');
phantom.exit(1);
}
var url = args[1],
page = require('webpage').create();
// Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`)
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onInitialized = function() {
timeoutRef = setTimeout(function(){
console.error('Test Run Failed. Timeout Exceeded. Took longer than '+ timeLimit / 1000 +' seconds.');
phantom.exit(1);
}, timeLimit);
};
page.onAlert = function(message) {
clearTimeout(timeoutRef);
phantom.exit(0);
};
page.open(url, function(status) {
if (status !== 'success') {
console.error('Unable to access network: ' + status);
phantom.exit(1);
}
});
})();
5) The error when running the app under PhantomJS
TypeError: 'undefined' is not a function (evaluating 'Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty)')
<path-to-deps>/wire-0.0.1/0.10.2/lib/object.js:13
<path-to-deps>/require-0.0.1/2.1.8/require.js:1635
<path-to-deps>/require-0.0.1/2.1.8/require.js:871
<path-to-deps>/require-0.0.1/2.1.8/require.js:1142
<path-to-deps>/require-0.0.1/2.1.8/require.js:779
<path-to-deps>/require-0.0.1/2.1.8/require.js:1169 in callGetModule
<path-to-deps>/require-0.0.1/2.1.8/require.js:1529
<path-to-deps>/require-0.0.1/2.1.8/require.js:1656
Error: Load timeout for modules: wire!wireContext_unnormalized2
http://requirejs.org/docs/errors.html#timeout
<path-to-deps>/require-0.0.1/2.1.8/require.js:138 in defaultOnError
<path-to-deps>/require-0.0.1/2.1.8/require.js:536 in onError
<path-to-deps>/require-0.0.1/2.1.8/require.js:691 in checkLoaded
<path-to-deps>/require-0.0.1/2.1.8/require.js:710
Test Run Failed. Timeout Exceeded. Took longer than 10 seconds.
As mentioned in the comments to the question, the origin of this problem is the fact that PhantomJS doesn't implement 'Function.prototype.bind()' function.
As suggested by the people from PhantomJS and WireJS, the problem would be fixed using an ES5 polyfill. The implementation suggested by MDN didn't help as it is a partial implementation of the specs. The implementation included in CujoJS/PolyJS has solved my problem. Now, WireJS is happy with PhantomJS.
Hereinafter is the new version of app.js
Cheers
You are right, Younes. PhantomJS doesn't support
Function.prototype.bind
for some reason.You can polyfill
Function.prototype.bind
by using either cujoJS/poly or kriskowal/es5-shim.