From e5b724e7be39ea8bd32789b8c868293cf0c8b40c Mon Sep 17 00:00:00 2001 From: Tobias Bocanegra Date: Tue, 3 Dec 2019 17:34:23 +0900 Subject: [PATCH] fix(compiler): allow to specify require when using compileToFunction() fixes #114 --- examples/jsdom/index.js | 5 ++--- src/compiler/Compiler.js | 24 ++++++++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/examples/jsdom/index.js b/examples/jsdom/index.js index 43b01ab..183c030 100644 --- a/examples/jsdom/index.js +++ b/examples/jsdom/index.js @@ -15,7 +15,7 @@ const { JSDOM } = require('jsdom'); const { Compiler, Runtime } = require('@adobe/htlengine'); const code = '' - + '' + + '' + '' + '${doc.title}\n' + '\n' @@ -40,8 +40,7 @@ async function run() { // setup the HTL compiler const compiler = new Compiler().withRuntimeVar('document'); - // compile the script to a executable template function - const template = await compiler.compileToFunction(code); + const template = await compiler.compileToFunction(code, __dirname, require); // generate the input data using JSDOM const document = new JSDOM(html).window.document; diff --git a/src/compiler/Compiler.js b/src/compiler/Compiler.js index ff3fbb8..99f7160 100644 --- a/src/compiler/Compiler.js +++ b/src/compiler/Compiler.js @@ -170,16 +170,24 @@ module.exports = class Compiler { * @async * @param {String} source HTL template code * @param {String} baseDir the base directory to resolve file references + * @param {NodeRequire} localRequire Require function that will be used to load modules. * @returns {Promise} the resulting function */ - async compileToFunction(source, baseDir) { + async compileToFunction(source, baseDir, localRequire = require) { const js = await this.compileToString(source, baseDir); - // poor men's module loader // eslint-disable-next-line no-new-func - const template = new Function('module', 'require', js); - const module = {}; - template.call(null, module, require); - return module.exports; + const template = new Function('exports', 'require', 'module', '__filename', '__dirname', js); + const mod = { + id: '.', + exports: {}, + filename: 'internal', + children: [], + parent: null, + dirname: baseDir, + require: localRequire, + }; + template.call(null, mod.exports, mod.require, mod, mod.filename, mod.dirname); + return mod.exports; } /** @@ -240,7 +248,7 @@ module.exports = class Compiler { i -= 1; } else { let file = c.filename; - if (file.startsWith('./')) { + if (file.startsWith('./') || file.startsWith('../')) { file = path.resolve(baseDir, file); } let name = mods[file]; @@ -301,7 +309,7 @@ module.exports = class Compiler { // make path relative to output directory if (path.isAbsolute(file)) { // eslint-disable-next-line no-param-reassign - file = path.relative(this._dir, file); + file = `.${path.sep}${path.relative(this._dir, file)}`; } imports += ` const ${name} = require(${JSON.stringify(file)});\n`; });