5 // Browserified version does not have esprima
7 // 1. For node.js just require module as deps
8 // 2. For browser try to require mudule via external AMD system.
9 // If not found - try to fallback to window.esprima. If not
10 // found too - then fail to parse.
13 // workaround to exclude package from browserify list.
14 var _require = require;
15 esprima = _require('esprima');
17 /* eslint-disable no-redeclare */
19 if (typeof window !== 'undefined') esprima = window.esprima;
22 var Type = require('../../type');
24 function resolveJavascriptFunction(data) {
25 if (data === null) return false;
28 var source = '(' + data + ')',
29 ast = esprima.parse(source, { range: true });
31 if (ast.type !== 'Program' ||
32 ast.body.length !== 1 ||
33 ast.body[0].type !== 'ExpressionStatement' ||
34 (ast.body[0].expression.type !== 'ArrowFunctionExpression' &&
35 ast.body[0].expression.type !== 'FunctionExpression')) {
45 function constructJavascriptFunction(data) {
48 var source = '(' + data + ')',
49 ast = esprima.parse(source, { range: true }),
53 if (ast.type !== 'Program' ||
54 ast.body.length !== 1 ||
55 ast.body[0].type !== 'ExpressionStatement' ||
56 (ast.body[0].expression.type !== 'ArrowFunctionExpression' &&
57 ast.body[0].expression.type !== 'FunctionExpression')) {
58 throw new Error('Failed to resolve function');
61 ast.body[0].expression.params.forEach(function (param) {
62 params.push(param.name);
65 body = ast.body[0].expression.body.range;
67 // Esprima's ranges include the first '{' and the last '}' characters on
68 // function expressions. So cut them out.
69 if (ast.body[0].expression.body.type === 'BlockStatement') {
70 /*eslint-disable no-new-func*/
71 return new Function(params, source.slice(body[0] + 1, body[1] - 1));
73 // ES6 arrow functions can omit the BlockStatement. In that case, just return
75 /*eslint-disable no-new-func*/
76 return new Function(params, 'return ' + source.slice(body[0], body[1]));
79 function representJavascriptFunction(object /*, style*/) {
80 return object.toString();
83 function isFunction(object) {
84 return Object.prototype.toString.call(object) === '[object Function]';
87 module.exports = new Type('tag:yaml.org,2002:js/function', {
89 resolve: resolveJavascriptFunction,
90 construct: constructJavascriptFunction,
91 predicate: isFunction,
92 represent: representJavascriptFunction