I have a module called util
with the methods getMutedColor
and some others. getMutedColor
relies on another called rand
in the same module.
page.includeJs('https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js', function() {
var util = require('./util');
var svg = page.evaluate(pageContext.pageExec, data, meta, util);
/** ... **/
}
I can call util.getMutedColor()
just fine within this scope but in my pageContext.pageExec
function, util.getMutedColor
no longer exists. The util
parameter is still an object, but I cannot call any of the exported methods:
TypeError: 'undefined' is not a function (evaluating 'util.getMutedColor()')
Is there a way to pass a self-contained module to a page?
No, it is not really possible. As seen in the docs:
Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.
The function that you pass to evaluate must be self-contained and the data that you pass cannot contain functions or objects that are created with new
. Those are stripped.
This means that you must copy the util
object completely into the pageExec
function.
If util
is too big to copy or if you use multiple functions of util
, you can try different things:
Serialize the functions and pass them as strings to the evaluate callback where you would instantiate them with new Function(string)
and bind them to the util
object.
var funcNames = [];
for(var prop in util) {
if (util.hasOwnProperty(prop) && typeof util[prop] === "function") {
funcNames.push(prop);
util[prop] = util[prop].toString();
}
}
util.__funcNames = funcNames; // make it a property of util
page.evaluate(pageContext.pageExec, data, meta, util);
and inside of pageContext.pageExec
:
util.__funcNames.forEach(function(funcName){
util[funcName] = new Function(util[funcName]);
});
Have only a single pageContext
function which contains everything and you can use a switch case
with a parameter that is passed every time to evaluate
to select the proper function inside of the single pageContext
function.
Use page.injectJs
to inject the utils. It would be necessary to namespace the utils in by checking if window
is present with something like that:
var util = {...};
if (window) {
window.util = util
} else if(module) {
module.exports = util;
}
Probably there are better scripts out there to do this depending on the environment.