1 // Not using strict mode here because strict mode has an impact on evaled source code
3 /* eslint-disable no-unused-vars, camelcase */
4 // Yep, they are unused intentionally. They are just available for convenience reasons.
5 var webpage = require("webpage");
6 var system = require("system");
7 var fs = require("fs");
8 var webserver = require("webserver");
9 var child_process = require("child_process");
10 var configPath = system.args[1];
11 var config = JSON.parse(fs.read(configPath));
12 /*eslint-enable no-unused-vars, camelcase */
15 var commandHandlers = {};
18 * Reads a line from stdin and calls the requested command handler. Calls itself after setTimeout 0.
21 // stdin.readLine() is sync and halts until a whole line is read
22 var line = system.stdin.readLine();
23 var message = JSON.parse(line);
24 var handler = commandHandlers[message.action];
27 throw new Error("Unknown action '" + message.action + "'");
36 * Returns a function that should be called to return the result for this message.
38 * @param {Object} message
41 function createResolver(message) {
43 * @param {Object} data
45 function resolve(data) {
48 id: message.done ? null : message.id,
58 * Returns a function that should be called to indicate that this message yielded to an error.
60 * @param {Object} message
63 function createRejecter(message) {
65 * @param {Object} data
67 function reject(data) {
71 throw new Error(data ? data.message || "Error" : "Error");
76 " -----------------------------------------------------------------------\n" +
87 id: message.done ? null : message.id,
97 * Runs message.data.src in the given context.
99 * @param {Object} message
100 * @param {Object} context
102 function run(message, context) {
103 var resolve = createResolver(message);
104 var reject = createRejecter(message);
107 evalSrc(message.data.src, context, resolve, reject);
114 * Helper function for run() to avoid scope pollution. `context`, `resolve` and `reject` are needed according
115 * to the serializeFn-module.
117 * @param {string} src
118 * @param {object} context
119 * @param {Function} resolve
120 * @param {Function} reject
122 function evalSrc(src, context, resolve, reject) {
123 eval(src); // eslint-disable-line
127 * Helper function that stringifies the given object and writes it to system.stdout
129 * @param {Object} message
131 function write(message) {
132 system.stdout.writeLine("message to node: " + JSON.stringify(message));
136 * Collection of request-able commands (as defined in the action-property of the message).
143 * The ping command is a neat trick so PhantomJS isn't stuck in the stdin.readLine()-loop
144 * while waiting for an asynchronous event. A ping-command is sent by node as long as it
145 * waits for PhantomJS to respond. We're responding with a pong to tell node that we're waiting
155 * Runs message.data.src in the default context.
157 * @param {Object} message
159 run: function (message) {
160 run(message, context);
164 * Runs message.data.src in the requested page context. If the page context doesn't exist, a new webpage
165 * is created implicitly.
167 * @param {Object} message
169 "run-on-page": function (message) {
170 var pageId = message.data.pageId;
171 var page = pages[pageId];
174 pages[pageId] = page = webpage.create();
181 // remove the config as it is not needed anymore
182 fs.remove(configPath);
184 // send hi to node so node knows that we're ready
185 system.stdout.writeLine("message to node: hi");