UNPKG

15.2 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const testcafe_hammerhead_1 = __importDefault(require("testcafe-hammerhead"));
7const asyncToGenerator_1 = __importDefault(require("babel-runtime/helpers/asyncToGenerator"));
8const lodash_1 = require("lodash");
9const load_babel_libs_1 = __importDefault(require("./load-babel-libs"));
10const runtime_1 = require("../errors/runtime");
11const types_1 = require("../errors/types");
12const ANONYMOUS_FN_RE = /^function\s*\*?\s*\(/;
13const ES6_OBJ_METHOD_NAME_RE = /^(\S+?)\s*\(/;
14const USE_STRICT_RE = /^('|")use strict('|");?/;
15const TRAILING_SEMICOLON_RE = /;\s*$/;
16const REGENERATOR_FOOTPRINTS_RE = /(_index\d+\.default|_regenerator\d+\.default|regeneratorRuntime)\.wrap\(function _callee\$\(_context\)/;
17const ASYNC_TO_GENERATOR_OUTPUT_CODE = asyncToGenerator_1.default(lodash_1.noop).toString();
18const babelArtifactPolyfills = {
19 'Promise': {
20 re: /_promise(\d+)\.default/,
21 getCode: match => `var _promise${match[1]} = { default: Promise };`,
22 removeMatchingCode: false
23 },
24 'Object.keys()': {
25 re: /_keys(\d+)\.default/,
26 getCode: match => `var _keys${match[1]} = { default: Object.keys };`,
27 removeMatchingCode: false
28 },
29 'JSON.stringify()': {
30 re: /_stringify(\d+)\.default/,
31 getCode: match => `var _stringify${match[1]} = { default: JSON.stringify };`,
32 removeMatchingCode: false
33 }
34};
35function getBabelOptions() {
36 const { presetFallback, transformForOfAsArray } = load_babel_libs_1.default();
37 return {
38 presets: [{ plugins: [transformForOfAsArray] }, presetFallback],
39 sourceMaps: false,
40 retainLines: true,
41 ast: false,
42 babelrc: false,
43 highlightCode: false
44 };
45}
46function downgradeES(fnCode) {
47 const { babel } = load_babel_libs_1.default();
48 const opts = getBabelOptions();
49 const compiled = babel.transform(fnCode, opts);
50 return compiled.code
51 .replace(USE_STRICT_RE, '')
52 .trim();
53}
54function addBabelArtifactsPolyfills(fnCode, dependenciesDefinition) {
55 let modifiedFnCode = fnCode;
56 const polyfills = Object
57 .values(babelArtifactPolyfills)
58 .reduce((polyfillsCode, polyfill) => {
59 const match = fnCode.match(polyfill.re);
60 if (match) {
61 if (polyfill.removeMatchingCode)
62 modifiedFnCode = modifiedFnCode.replace(polyfill.re, '');
63 return polyfillsCode + polyfill.getCode(match);
64 }
65 return polyfillsCode;
66 }, '');
67 return `(function(){${dependenciesDefinition}${polyfills} return ${modifiedFnCode}})();`;
68}
69function getDependenciesDefinition(dependencies) {
70 return Object
71 .keys(dependencies)
72 .reduce((code, name) => {
73 return code + `var ${name}=__dependencies$['${name}'];`;
74 }, '');
75}
76function makeFnCodeSuitableForParsing(fnCode) {
77 // NOTE: 'function() {}' -> '(function() {})'
78 if (ANONYMOUS_FN_RE.test(fnCode))
79 return `(${fnCode})`;
80 // NOTE: 'myFn () {}' -> 'function myFn() {}'
81 const match = fnCode.match(ES6_OBJ_METHOD_NAME_RE);
82 if (match && match[1] !== 'function')
83 return `function ${fnCode}`;
84 return fnCode;
85}
86function compileClientFunction(fnCode, dependencies, instantiationCallsiteName, compilationCallsiteName) {
87 if (fnCode === ASYNC_TO_GENERATOR_OUTPUT_CODE)
88 throw new runtime_1.ClientFunctionAPIError(compilationCallsiteName, instantiationCallsiteName, types_1.RUNTIME_ERRORS.regeneratorInClientFunctionCode);
89 fnCode = makeFnCodeSuitableForParsing(fnCode);
90 // NOTE: we need to recompile ES6 code for the browser if we are on newer versions of Node.
91 fnCode = downgradeES(fnCode);
92 fnCode = testcafe_hammerhead_1.default.processScript(fnCode, false);
93 // NOTE: check compiled code for regenerator injection: we have either generator
94 // recompiled in Node.js 4+ for client or async function declared in function code.
95 if (REGENERATOR_FOOTPRINTS_RE.test(fnCode))
96 throw new runtime_1.ClientFunctionAPIError(compilationCallsiteName, instantiationCallsiteName, types_1.RUNTIME_ERRORS.regeneratorInClientFunctionCode);
97 if (!TRAILING_SEMICOLON_RE.test(fnCode))
98 fnCode += ';';
99 const dependenciesDefinition = dependencies ? getDependenciesDefinition(dependencies) : '';
100 return addBabelArtifactsPolyfills(fnCode, dependenciesDefinition);
101}
102exports.default = compileClientFunction;
103module.exports = exports.default;
104//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcGlsZS1jbGllbnQtZnVuY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tcGlsZXIvY29tcGlsZS1jbGllbnQtZnVuY3Rpb24uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw4RUFBNkM7QUFDN0MsOEZBQXNFO0FBQ3RFLG1DQUE4QjtBQUM5Qix3RUFBOEM7QUFDOUMsK0NBQTJEO0FBQzNELDJDQUFpRDtBQUVqRCxNQUFNLGVBQWUsR0FBa0Isc0JBQXNCLENBQUM7QUFDOUQsTUFBTSxzQkFBc0IsR0FBVyxjQUFjLENBQUM7QUFDdEQsTUFBTSxhQUFhLEdBQW9CLHlCQUF5QixDQUFDO0FBQ2pFLE1BQU0scUJBQXFCLEdBQVksT0FBTyxDQUFDO0FBQy9DLE1BQU0seUJBQXlCLEdBQVEsd0dBQXdHLENBQUM7QUFDaEosTUFBTSw4QkFBOEIsR0FBRywwQkFBZ0IsQ0FBQyxhQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUV6RSxNQUFNLHNCQUFzQixHQUFHO0lBQzNCLFNBQVMsRUFBRTtRQUNQLEVBQUUsRUFBa0Isd0JBQXdCO1FBQzVDLE9BQU8sRUFBYSxLQUFLLENBQUMsRUFBRSxDQUFDLGVBQWUsS0FBSyxDQUFDLENBQUMsQ0FBQywwQkFBMEI7UUFDOUUsa0JBQWtCLEVBQUUsS0FBSztLQUM1QjtJQUVELGVBQWUsRUFBRTtRQUNiLEVBQUUsRUFBa0IscUJBQXFCO1FBQ3pDLE9BQU8sRUFBYSxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyw4QkFBOEI7UUFDL0Usa0JBQWtCLEVBQUUsS0FBSztLQUM1QjtJQUVELGtCQUFrQixFQUFFO1FBQ2hCLEVBQUUsRUFBa0IsMEJBQTBCO1FBQzlDLE9BQU8sRUFBYSxLQUFLLENBQUMsRUFBRSxDQUFDLGlCQUFpQixLQUFLLENBQUMsQ0FBQyxDQUFDLGlDQUFpQztRQUN2RixrQkFBa0IsRUFBRSxLQUFLO0tBQzVCO0NB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QUMsQ0FBQztJQUU5QywyRkFBMkY7SUFDM0YsTUFBTSxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM3QixNQUFNLEdBQUcsNkJBQVUsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRWpELGdGQUFnRjtJQUNoRixtRkFBbUY7SUFDbkYsSUFBSSx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQ3RDLE1BQU0sSUFBSSxnQ0FBc0IsQ0FBQyx1QkFBdUIsRUFBRSx5QkFBeUIsRUFBRSxzQkFBYyxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFFekksSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDbkMsTUFBTSxJQUFJLEdBQUcsQ0FBQztJQUVsQixNQUFNLHNCQUFzQixHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMseUJBQXlCLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUUzRixPQUFPLDBCQUEwQixDQUFDLE1BQU0sRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO0FBQ3RFLENBQUM7QUFyQkQsd0NBcUJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGhhbW1lcmhlYWQgZnJvbSAndGVzdGNhZmUtaGFtbWVyaGVhZCc7XG5pbXBvcnQgYXN5bmNUb0dlbmVyYXRvciBmcm9tICdiYWJlbC1ydW50aW1lL2hlbHBlcnMvYXN5bmNUb0dlbmVyYXRvcic7XG5pbXBvcnQgeyBub29wIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBsb2FkQmFiZWxMaWJzIGZyb20gJy4vbG9hZC1iYWJlbC1saWJzJztcbmltcG9ydCB7IENsaWVudEZ1bmN0aW9uQVBJRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMvcnVudGltZSc7XG5pbXBvcnQgeyBSVU5USU1FX0VSUk9SUyB9IGZyb20gJy4uL2Vycm9ycy90eXBlcyc7XG5cbmNvbnN0IEFOT05ZTU9VU19GTl9SRSAgICAgICAgICAgICAgICA9IC9eZnVuY3Rpb25cXHMqXFwqP1xccypcXCgvO1xuY29uc3QgRVM2X09CSl9NRVRIT0RfTkFNRV9SRSAgICAgICAgID0gL14oXFxTKz8pXFxzKlxcKC87XG5jb25zdCBVU0VfU1RSSUNUX1JFICAgICAgICAgICAgICAgICAgPSAvXignfFwiKXVzZSBzdHJpY3QoJ3xcIik7Py87XG5jb25zdCBUUkFJTElOR19TRU1JQ09MT05fUkUgICAgICAgICAgPSAvO1xccyokLztcbmNvbnN0IFJFR0VORVJBVE9SX0ZPT1RQUklOVFNfUkUgICAgICA9IC8oX2luZGV4XFxkK1xcLmRlZmF1bHR8X3JlZ2VuZXJhdG9yXFxkK1xcLmRlZmF1bHR8cmVnZW5lcmF0b3JSdW50aW1lKVxcLndyYXBcXChmdW5jdGlvbiBfY2FsbGVlXFwkXFwoX2NvbnRleHRcXCkvO1xuY29uc3QgQVNZTkNfVE9fR0VORVJBVE9SX09VVFBVVF9DT0RFID0gYXN5bmNUb0dlbmVyYXRvcihub29wKS50b1N0cmluZygpO1xuXG5jb25zdCBiYWJlbEFydGlmYWN0UG9seWZpbGxzID0ge1xuICAgICdQcm9taXNlJzoge1xuICAgICAgICByZTogICAgICAgICAgICAgICAgIC9fcHJvbWlzZShcXGQrKVxcLmRlZmF1bHQvLFxuICAgICAgICBnZXRDb2RlOiAgICAgICAgICAgIG1hdGNoID0+IGB2YXIgX3Byb21pc2Uke21hdGNoWzFdfSA9IHsgZGVmYXVsdDogUHJvbWlzZSB9O2AsXG4gICAgICAgIHJlbW92ZU1hdGNoaW5nQ29kZTogZmFsc2VcbiAgICB9LFxuXG4gICAgJ09iamVjdC5rZXlzKCknOiB7XG4gICAgICAgIHJlOiAgICAgICAgICAgICAgICAgL19rZXlzKFxcZCspXFwuZGVmYXVsdC8sXG4gICAgICAgIGdldENvZGU6ICAgICAgICAgICAgbWF0Y2ggPT4gYHZhciBfa2V5cyR7bWF0Y2hbMV19ID0geyBkZWZhdWx0OiBPYmplY3Qua2V5cyB9O2AsXG4gICAgICAgIHJlbW92ZU1hdGNoaW5nQ29kZTogZmFsc2VcbiAgICB9LFxuXG4gICAgJ0pTT04uc3RyaW5naWZ5KCknOiB7XG4gICAgICAgIHJlOiAgICAgICAgICAgICAgICAgL19zdHJpbmdpZnkoXFxkKylcXC5kZWZhdWx0LyxcbiAgICAgICAgZ2V0Q29kZTogICAgICAgICAgICBtYXRjaCA9PiBgdmFyIF9zdHJpbmdpZnkke21hdGNoWzFdfSA9IHsgZGVmYXVsdDogSlNPTi5zdHJpbmdpZnkgfTtgLFxuICAgICAgICByZW1vdmVNYXRjaGluZ0NvZGU6IGZhbHNlXG4gICAgfVxufTtcblxuXG5mdW5jdGlvbiBnZXRCYWJlbE9wdGlvbnMgKCkge1xuICAgIGNvbnN0IHsgcHJlc2V0RmFsbGJhY2ssIHRyYW5zZm9ybUZvck9mQXNBcnJheSB9ID0gbG9hZEJhYmVsTGlicygpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgcHJlc2V0czogICAgICAgW3sgcGx1Z2luczogW3RyYW5zZm9ybUZvck9mQXNBcnJheV0gfSwgcHJlc2V0RmFsbGJhY2tdLFxuICAgICAgICBzb3VyY2VNYXBzOiAgICBmYWxzZSxcbiAgICAgICAgcmV0YWluTGluZXM6ICAgdHJ1ZSxcbiAgICAgICAgYXN0OiAgICAgICAgICAgZmFsc2UsXG4gICAgICAgIGJhYmVscmM6ICAgICAgIGZhbHNlLFxuICAgICAgICBoaWdobGlnaHRDb2RlOiBmYWxzZVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGRvd25ncmFkZUVTIChmbkNvZGUpIHtcbiAgICBjb25zdCB7IGJhYmVsIH0gPSBsb2FkQmFiZWxMaWJzKCk7XG5cbiAgICBjb25zdCBvcHRzICAgICA9IGdldEJhYmVsT3B0aW9ucygpO1xuICAgIGNvbnN0IGNvbXBpbGVkID0gYmFiZWwudHJhbnNmb3JtKGZuQ29kZSwgb3B0cyk7XG5cbiAgICByZXR1cm4gY29tcGlsZWQuY29kZVxuICAgICAgICAucmVwbGFjZShVU0VfU1RSSUNUX1JFLCAnJylcbiAgICAgICAgLnRyaW0oKTtcbn1cblxuZnVuY3Rpb24gYWRkQmFiZWxBcnRpZmFjdHNQb2x5ZmlsbHMgKGZuQ29kZSwgZGVwZW5kZW5jaWVzRGVmaW5pdGlvbikge1xuICAgIGxldCBtb2RpZmllZEZuQ29kZSA9IGZuQ29kZTtcblxuICAgIGNvbnN0IHBvbHlmaWxscyA9IE9iamVjdFxuICAgICAgICAudmFsdWVzKGJhYmVsQXJ0aWZhY3RQb2x5ZmlsbHMpXG4gICAgICAgIC5yZWR1Y2UoKHBvbHlmaWxsc0NvZGUsIHBvbHlmaWxsKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBtYXRjaCA9IGZuQ29kZS5tYXRjaChwb2x5ZmlsbC5yZSk7XG5cbiAgICAgICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChwb2x5ZmlsbC5yZW1vdmVNYXRjaGluZ0NvZGUpXG4gICAgICAgICAgICAgICAgICAgIG1vZGlmaWVkRm5Db2RlID0gbW9kaWZpZWRGbkNvZGUucmVwbGFjZShwb2x5ZmlsbC5yZSwgJycpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvbHlmaWxsc0NvZGUgKyBwb2x5ZmlsbC5nZXRDb2RlKG1hdGNoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHBvbHlmaWxsc0NvZGU7XG4gICAgICAgIH0sICcnKTtcblxuICAgIHJldHVybiBgKGZ1bmN0aW9uKCl7JHtkZXBlbmRlbmNpZXNEZWZpbml0aW9ufSR7cG9seWZpbGxzfSByZXR1cm4gJHttb2RpZmllZEZuQ29kZX19KSgpO2A7XG59XG5cbmZ1bmN0aW9uIGdldERlcGVuZGVuY2llc0RlZmluaXRpb24gKGRlcGVuZGVuY2llcykge1xuICAgIHJldHVybiBPYmplY3RcbiAgICAgICAgLmtleXMoZGVwZW5kZW5jaWVzKVxuICAgICAgICAucmVkdWNlKChjb2RlLCBuYW1lKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gY29kZSArIGB2YXIgJHtuYW1lfT1fX2RlcGVuZGVuY2llcyRbJyR7bmFtZX0nXTtgO1xuICAgICAgICB9LCAnJyk7XG59XG5cbmZ1bmN0aW9uIG1ha2VGbkNvZGVTdWl0YWJsZUZvclBhcnNpbmcgKGZuQ29kZSkge1xuICAgIC8vIE5PVEU6ICdmdW5jdGlvbigpIHt9JyAtPiAnKGZ1bmN0aW9uKCkge30pJ1xuICAgIGlmIChBTk9OWU1PVVNfRk5fUkUudGVzdChmbkNvZGUpKVxuICAgICAgICByZXR1cm4gYCgke2ZuQ29kZX0pYDtcblxuICAgIC8vIE5PVEU6ICdteUZuICgpIHt9JyAtPiAnZnVuY3Rpb24gbXlGbigpIHt9J1xuICAgIGNvbnN0IG1hdGNoID0gZm5Db2RlLm1hdGNoKEVTNl9PQkpfTUVUSE9EX05BTUVfUkUpO1xuXG4gICAgaWYgKG1hdGNoICYmIG1hdGNoWzFdICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICByZXR1cm4gYGZ1bmN0aW9uICR7Zm5Db2RlfWA7XG5cbiAgICByZXR1cm4gZm5Db2RlO1xufVxuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBjb21waWxlQ2xpZW50RnVuY3Rpb24gKGZuQ29kZSwgZGVwZW5kZW5jaWVzLCBpbnN0YW50aWF0aW9uQ2FsbHNpdGVOYW1lLCBjb21waWxhdGlvbkNhbGxzaXRlTmFtZSkge1xuICAgIGlmIChmbkNvZGUgPT09IEFTWU5DX1RPX0dFTkVSQVRPUl9PVVRQVVRfQ09ERSlcbiAgICAgICAgdGhyb3cgbmV3IENsaWVudEZ1bmN0aW9uQVBJRXJyb3IoY29tcGlsYXRpb25DYWxsc2l0ZU5hbWUsIGluc3RhbnRpYXRpb25DYWxsc2l0ZU5hbWUsIFJVTlRJTUVfRVJST1JTLnJlZ2VuZXJhdG9ySW5DbGllbnRGdW5jdGlvbkNvZGUpO1xuXG4gICAgZm5Db2RlID0gbWFrZUZuQ29kZVN1aXRhYmxlRm9yUGFyc2luZyhmbkNvZGUpO1xuXG4gICAgLy8gTk9URTogd2UgbmVlZCB0byByZWNvbXBpbGUgRVM2IGNvZGUgZm9yIHRoZSBicm93c2VyIGlmIHdlIGFyZSBvbiBuZXdlciB2ZXJzaW9ucyBvZiBOb2RlLlxuICAgIGZuQ29kZSA9IGRvd25ncmFkZUVTKGZuQ29kZSk7XG4gICAgZm5Db2RlID0gaGFtbWVyaGVhZC5wcm9jZXNzU2NyaXB0KGZuQ29kZSwgZmFsc2UpO1xuXG4gICAgLy8gTk9URTogY2hlY2sgY29tcGlsZWQgY29kZSBmb3IgcmVnZW5lcmF0b3IgaW5qZWN0aW9uOiB3ZSBoYXZlIGVpdGhlciBnZW5lcmF0b3JcbiAgICAvLyByZWNvbXBpbGVkIGluIE5vZGUuanMgNCsgZm9yIGNsaWVudCBvciBhc3luYyBmdW5jdGlvbiBkZWNsYXJlZCBpbiBmdW5jdGlvbiBjb2RlLlxuICAgIGlmIChSRUdFTkVSQVRPUl9GT09UUFJJTlRTX1JFLnRlc3QoZm5Db2RlKSlcbiAgICAgICAgdGhyb3cgbmV3IENsaWVudEZ1bmN0aW9uQVBJRXJyb3IoY29tcGlsYXRpb25DYWxsc2l0ZU5hbWUsIGluc3RhbnRpYXRpb25DYWxsc2l0ZU5hbWUsIFJVTlRJTUVfRVJST1JTLnJlZ2VuZXJhdG9ySW5DbGllbnRGdW5jdGlvbkNvZGUpO1xuXG4gICAgaWYgKCFUUkFJTElOR19TRU1JQ09MT05fUkUudGVzdChmbkNvZGUpKVxuICAgICAgICBmbkNvZGUgKz0gJzsnO1xuXG4gICAgY29uc3QgZGVwZW5kZW5jaWVzRGVmaW5pdGlvbiA9IGRlcGVuZGVuY2llcyA/IGdldERlcGVuZGVuY2llc0RlZmluaXRpb24oZGVwZW5kZW5jaWVzKSA6ICcnO1xuXG4gICAgcmV0dXJuIGFkZEJhYmVsQXJ0aWZhY3RzUG9seWZpbGxzKGZuQ29kZSwgZGVwZW5kZW5jaWVzRGVmaW5pdGlvbik7XG59XG4iXX0=
\No newline at end of file