Commit 107eedf4 107eedf48cfcb0b8bef808b9e4617f99aefc2a0f by Nicolas Perriault

cleaner bootstrap.js

1 parent 6e6cfb58
...@@ -31,10 +31,13 @@ ...@@ -31,10 +31,13 @@
31 /*global console phantom require*/ 31 /*global console phantom require*/
32 /*jshint maxstatements:30 maxcomplexity:10*/ 32 /*jshint maxstatements:30 maxcomplexity:10*/
33 33
34 // phantom check
34 if (!phantom) { 35 if (!phantom) {
35 console.error('CasperJS needs to be executed in a PhantomJS environment http://phantomjs.org/'); 36 console.error('CasperJS needs to be executed in a PhantomJS environment http://phantomjs.org/');
37 phantom.exit(1);
36 } 38 }
37 39
40 // required version check
38 if (phantom.version.major === 1 && phantom.version.minor < 7) { 41 if (phantom.version.major === 1 && phantom.version.minor < 7) {
39 console.error('CasperJS needs at least PhantomJS v1.7 or later.'); 42 console.error('CasperJS needs at least PhantomJS v1.7 or later.');
40 phantom.exit(1); 43 phantom.exit(1);
...@@ -60,94 +63,20 @@ var CasperError = function CasperError(msg) { ...@@ -60,94 +63,20 @@ var CasperError = function CasperError(msg) {
60 }; 63 };
61 CasperError.prototype = Object.getPrototypeOf(new Error()); 64 CasperError.prototype = Object.getPrototypeOf(new Error());
62 65
63 // Patching fs 66 // casperjs env initialization
64 (function _fs(fs) { 67 (function(global, phantom){
65 "use strict"; 68 "use strict";
66 if (!fs.hasOwnProperty('basename')) { 69 // phantom args
67 fs.basename = function basename(path) { 70 // NOTE: we can't use require('system').args here for some very obscure reason
68 return path.replace(/.*\//, ''); 71 // do not even attempt at using it as it creates infinite recursion
69 }; 72 var phantomArgs = phantom.args;
70 }
71 if (!fs.hasOwnProperty('dirname')) {
72 fs.dirname = function dirname(path) {
73 return path.replace(/\\/g, '/').replace(/\/[^\/]*$/, '');
74 };
75 }
76 if (!fs.hasOwnProperty('isWindows')) {
77 fs.isWindows = function isWindows() {
78 var testPath = arguments[0] || this.workingDirectory;
79 return (/^[a-z]{1,2}:/i).test(testPath) || testPath.indexOf("\\\\") === 0;
80 };
81 }
82 if (!fs.hasOwnProperty('pathJoin')) {
83 fs.pathJoin = function pathJoin() {
84 return Array.prototype.join.call(arguments, this.separator);
85 };
86 }
87 return fs;
88 })(require('fs'));
89 73
90 // Patched require to allow loading of native casperjs modules. 74 if (phantom.casperLoaded) {
91 // Every casperjs native module have to first call this function in order to 75 return;
92 // load a native casperjs module:
93 //
94 // var require = patchRequire(require);
95 // var utils = require('utils');
96 function patchRequire(require) {
97 "use strict";
98 if (require.patched) {
99 return require;
100 } 76 }
101 var fs = require('fs');
102 var patchedRequire = function _require(path) {
103 console.log(path);
104 var moduleFilePath = fs.pathJoin(phantom.casperPath, 'modules', path + '.js');
105 if (!fs.exists(moduleFilePath)) {
106 console.log('normal');
107 return require(path); // native phantomjs' require() behavior
108 }
109 try {
110 console.log('custom');
111 return require(moduleFilePath);
112 } catch (e) {
113 var error = new CasperError('__mod_error(' + path + ':' + e.line + '):: ' + e);
114 error.file = moduleFilePath;
115 error.line = e.line;
116 error.stack = e.stack;
117 error.stackArray = JSON.parse(JSON.stringify(e.stackArray));
118 if (error.stackArray.length > 0) {
119 error.stackArray[0].sourceURL = moduleFilePath;
120 }
121 throw error;
122 }
123 };
124 patchedRequire.cache = require.cache;
125 patchedRequire.extensions = require.extensions;
126 patchedRequire.stubs = require.stubs;
127 patchedRequire.patched = true;
128 return patchedRequire;
129 }
130 77
131 try { 78 // Hooks in default phantomjs error handler to print a hint when a possible
132 bootstrap(window); 79 // casperjs command misuse is detected.
133 } catch (e) {
134 console.error(e);
135 (e.stackArray || []).forEach(function(entry) {
136 console.error(' In ' + entry.sourceURL + ':' + entry.line);
137 });
138 phantom.exit(1);
139 }
140
141 // bootstrap
142 function bootstrap(global) {
143 "use strict";
144 var phantomArgs = require('system').args;
145
146 /**
147 * Hooks in default phantomjs error handler to print a hint when a possible
148 * casperjs command misuse is detected.
149 *
150 */
151 phantom.onError = function onPhantomError(msg, trace) { 80 phantom.onError = function onPhantomError(msg, trace) {
152 phantom.defaultErrorHandler.apply(phantom, arguments); 81 phantom.defaultErrorHandler.apply(phantom, arguments);
153 if (msg.indexOf("ReferenceError: Can't find variable: casper") === 0) { 82 if (msg.indexOf("ReferenceError: Can't find variable: casper") === 0) {
...@@ -155,81 +84,92 @@ function bootstrap(global) { ...@@ -155,81 +84,92 @@ function bootstrap(global) {
155 } 84 }
156 }; 85 };
157 86
158 /** 87 // Patching fs
159 * Loads and initialize the CasperJS environment. 88 var fs = (function patchFs(fs) {
160 */ 89 if (!fs.hasOwnProperty('basename')) {
161 phantom.loadCasper = function loadCasper() { 90 fs.basename = function basename(path) {
162 var fs = require('fs'); 91 return path.replace(/.*\//, '');
163 // casper root path 92 };
164 if (!phantom.casperPath) { 93 }
165 try { 94 if (!fs.hasOwnProperty('dirname')) {
166 phantom.casperPath = phantom.args.map(function _map(i) { 95 fs.dirname = function dirname(path) {
167 var match = i.match(/^--casper-path=(.*)/); 96 return path.replace(/\\/g, '/').replace(/\/[^\/]*$/, '');
168 if (match) { 97 };
169 return fs.absolute(match[1]); 98 }
170 } 99 if (!fs.hasOwnProperty('isWindows')) {
171 }).filter(function _filter(path) { 100 fs.isWindows = function isWindows() {
172 return fs.isDirectory(path); 101 var testPath = arguments[0] || this.workingDirectory;
173 }).pop(); 102 return (/^[a-z]{1,2}:/i).test(testPath) || testPath.indexOf("\\\\") === 0;
174 } catch (e) {} 103 };
104 }
105 if (fs.hasOwnProperty('joinPath')) {
106 fs.pathJoin = fs.joinPath;
107 } else if (!fs.hasOwnProperty('pathJoin')) {
108 fs.pathJoin = function pathJoin() {
109 return Array.prototype.join.call(arguments, this.separator);
110 };
175 } 111 }
112 return fs;
113 })(require('fs'));
176 114
177 if (!phantom.casperPath) { 115 // CasperJS root path
116 if (!phantom.casperPath) {
117 try {
118 phantom.casperPath = phantom.args.map(function _map(arg) {
119 var match = arg.match(/^--casper-path=(.*)/);
120 if (match) {
121 return fs.absolute(match[1]);
122 }
123 }).filter(function _filter(path) {
124 return fs.isDirectory(path);
125 }).pop();
126 } catch (e) {
178 console.error("Couldn't find nor compute phantom.casperPath, exiting."); 127 console.error("Couldn't find nor compute phantom.casperPath, exiting.");
179 phantom.exit(1); 128 phantom.exit(1);
180 } 129 }
130 }
181 131
182 // Embedded, up-to-date, validatable & controlable CoffeeScript 132 // Patched require to allow loading of native casperjs modules.
183 phantom.injectJs(fs.pathJoin(phantom.casperPath, 'modules', 'vendors', 'coffee-script.js')); 133 // Every casperjs native module have to first call this function in order to
184 134 // load a native casperjs module:
185 // CasperJS version, extracted from package.json - see http://semver.org/ 135 //
186 phantom.casperVersion = (function getVersion(path) { 136 // var require = patchRequire(require);
187 var parts, patchPart, pkg, pkgFile; 137 // var utils = require('utils');
188 var fs = require('fs'); 138 function patchRequire(require) {
189 pkgFile = fs.absolute(fs.pathJoin(path, 'package.json')); 139 if (require.patched) {
190 if (!fs.exists(pkgFile)) { 140 return require;
191 throw new CasperError('Cannot find package.json at ' + pkgFile); 141 }
142 var patchedRequire = function _require(path) {
143 var moduleFilePath = fs.pathJoin(phantom.casperPath, 'modules', path + '.js');
144 if (!fs.exists(moduleFilePath)) {
145 return require(path); // native phantomjs' require() behavior
192 } 146 }
193 try { 147 try {
194 pkg = JSON.parse(require('fs').read(pkgFile)); 148 return require(moduleFilePath);
195 } catch (e) { 149 } catch (e) {
196 throw new CasperError('Cannot read package file contents: ' + e); 150 var error = new CasperError('__mod_error(' + path + ':' + e.line + '):: ' + e);
197 } 151 error.file = moduleFilePath;
198 parts = pkg.version.trim().split("."); 152 error.line = e.line;
199 if (parts.length < 3) { 153 error.stack = e.stack;
200 throw new CasperError("Invalid version number"); 154 error.stackArray = JSON.parse(JSON.stringify(e.stackArray));
201 } 155 if (error.stackArray.length > 0) {
202 patchPart = parts[2].split('-'); 156 error.stackArray[0].sourceURL = moduleFilePath;
203 return {
204 major: ~~parts[0] || 0,
205 minor: ~~parts[1] || 0,
206 patch: ~~patchPart[0] || 0,
207 ident: patchPart[1] || "",
208 toString: function toString() {
209 var version = [this.major, this.minor, this.patch].join('.');
210 if (this.ident) {
211 version = [version, this.ident].join('-');
212 }
213 return version;
214 } 157 }
215 }; 158 throw error;
216 })(phantom.casperPath); 159 }
217 160 };
218 // patch require (must be called in every casperjs module as of 1.1) 161 patchedRequire.cache = require.cache;
219 window.require = patchRequire(global.require); 162 patchedRequire.extensions = require.extensions;
220 163 patchedRequire.stubs = require.stubs;
221 // casper cli args 164 patchedRequire.patched = true;
222 phantom.casperArgs = require('cli').parse(phantomArgs); 165 return patchedRequire;
223 166 }
224 // loaded status 167 global.patchRequire = patchRequire;
225 phantom.casperLoaded = true;
226 };
227 168
228 /** 169 /**
229 * Initializes the CasperJS Command Line Interface. 170 * Initializes the CasperJS Command Line Interface.
230 */ 171 */
231 phantom.initCasperCli = function initCasperCli() { 172 function initCasperCli() {
232 var fs = require("fs");
233 var baseTestsPath = fs.pathJoin(phantom.casperPath, 'tests'); 173 var baseTestsPath = fs.pathJoin(phantom.casperPath, 'tests');
234 174
235 if (!!phantom.casperArgs.options.version) { 175 if (!!phantom.casperArgs.options.version) {
...@@ -268,18 +208,57 @@ function bootstrap(global) { ...@@ -268,18 +208,57 @@ function bootstrap(global) {
268 208
269 // filter out the called script name from casper args 209 // filter out the called script name from casper args
270 phantom.casperArgs.drop(phantom.casperScript); 210 phantom.casperArgs.drop(phantom.casperScript);
211 }
212
213 // Embedded, up-to-date, validatable & controlable CoffeeScript
214 phantom.injectJs(fs.pathJoin(phantom.casperPath, 'modules', 'vendors', 'coffee-script.js'));
271 215
272 // passed casperjs script execution 216 // CasperJS version, extracted from package.json - see http://semver.org/
273 if (!phantom.injectJs(phantom.casperScript)) { 217 phantom.casperVersion = (function getVersion(path) {
274 throw new CasperError('Unable to load script ' + phantom.casperScript + '; check file syntax'); 218 var parts, patchPart, pkg, pkgFile;
219 pkgFile = fs.absolute(fs.pathJoin(path, 'package.json'));
220 if (!fs.exists(pkgFile)) {
221 throw new CasperError('Cannot find package.json at ' + pkgFile);
275 } 222 }
276 }; 223 try {
224 pkg = JSON.parse(require('fs').read(pkgFile));
225 } catch (e) {
226 throw new CasperError('Cannot read package file contents: ' + e);
227 }
228 parts = pkg.version.trim().split(".");
229 if (parts.length < 3) {
230 throw new CasperError("Invalid version number");
231 }
232 patchPart = parts[2].split('-');
233 return {
234 major: ~~parts[0] || 0,
235 minor: ~~parts[1] || 0,
236 patch: ~~patchPart[0] || 0,
237 ident: patchPart[1] || "",
238 toString: function toString() {
239 var version = [this.major, this.minor, this.patch].join('.');
240 if (this.ident) {
241 version = [version, this.ident].join('-');
242 }
243 return version;
244 }
245 };
246 })(phantom.casperPath);
277 247
278 if (!phantom.casperLoaded) { 248 // patch require (must be called in every casperjs module as of 1.1)
279 phantom.loadCasper(); 249 global.require = patchRequire(global.require);
280 } 250
251 // casper cli args
252 phantom.casperArgs = require('cli').parse(phantomArgs);
281 253
282 if (true === phantom.casperArgs.get('cli')) { 254 if (true === phantom.casperArgs.get('cli')) {
283 phantom.initCasperCli(); 255 initCasperCli();
284 } 256 }
285 } 257
258 phantom.casperLoaded = true;
259
260 // passed casperjs script execution
261 if (!phantom.injectJs(phantom.casperScript)) {
262 throw new CasperError('Unable to load script ' + phantom.casperScript + '; check file syntax');
263 }
264 })(window, phantom);
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
30 30
31 /*global CasperError console exports phantom __utils__ patchRequire*/ 31 /*global CasperError console exports phantom __utils__ patchRequire*/
32 32
33 //var require = patchRequire(require); 33 var require = patchRequire(require);
34 var colorizer = require('colorizer'); 34 var colorizer = require('colorizer');
35 var events = require('events'); 35 var events = require('events');
36 var fs = require('fs'); 36 var fs = require('fs');
......