| 'use strict'; | 
|   | 
| var esprima; | 
|   | 
| // Browserified version does not have esprima | 
| // | 
| // 1. For node.js just require module as deps | 
| // 2. For browser try to require mudule via external AMD system. | 
| //    If not found - try to fallback to window.esprima. If not | 
| //    found too - then fail to parse. | 
| // | 
| try { | 
|   // workaround to exclude package from browserify list. | 
|   var _require = require; | 
|   esprima = _require('esprima'); | 
| } catch (_) { | 
|   /* eslint-disable no-redeclare */ | 
|   /* global window */ | 
|   if (typeof window !== 'undefined') esprima = window.esprima; | 
| } | 
|   | 
| var Type = require('../../type'); | 
|   | 
| function resolveJavascriptFunction(data) { | 
|   if (data === null) return false; | 
|   | 
|   try { | 
|     var source = '(' + data + ')', | 
|         ast    = esprima.parse(source, { range: true }); | 
|   | 
|     if (ast.type                    !== 'Program'             || | 
|         ast.body.length             !== 1                     || | 
|         ast.body[0].type            !== 'ExpressionStatement' || | 
|         (ast.body[0].expression.type !== 'ArrowFunctionExpression' && | 
|           ast.body[0].expression.type !== 'FunctionExpression')) { | 
|       return false; | 
|     } | 
|   | 
|     return true; | 
|   } catch (err) { | 
|     return false; | 
|   } | 
| } | 
|   | 
| function constructJavascriptFunction(data) { | 
|   /*jslint evil:true*/ | 
|   | 
|   var source = '(' + data + ')', | 
|       ast    = esprima.parse(source, { range: true }), | 
|       params = [], | 
|       body; | 
|   | 
|   if (ast.type                    !== 'Program'             || | 
|       ast.body.length             !== 1                     || | 
|       ast.body[0].type            !== 'ExpressionStatement' || | 
|       (ast.body[0].expression.type !== 'ArrowFunctionExpression' && | 
|         ast.body[0].expression.type !== 'FunctionExpression')) { | 
|     throw new Error('Failed to resolve function'); | 
|   } | 
|   | 
|   ast.body[0].expression.params.forEach(function (param) { | 
|     params.push(param.name); | 
|   }); | 
|   | 
|   body = ast.body[0].expression.body.range; | 
|   | 
|   // Esprima's ranges include the first '{' and the last '}' characters on | 
|   // function expressions. So cut them out. | 
|   if (ast.body[0].expression.body.type === 'BlockStatement') { | 
|     /*eslint-disable no-new-func*/ | 
|     return new Function(params, source.slice(body[0] + 1, body[1] - 1)); | 
|   } | 
|   // ES6 arrow functions can omit the BlockStatement. In that case, just return | 
|   // the body. | 
|   /*eslint-disable no-new-func*/ | 
|   return new Function(params, 'return ' + source.slice(body[0], body[1])); | 
| } | 
|   | 
| function representJavascriptFunction(object /*, style*/) { | 
|   return object.toString(); | 
| } | 
|   | 
| function isFunction(object) { | 
|   return Object.prototype.toString.call(object) === '[object Function]'; | 
| } | 
|   | 
| module.exports = new Type('tag:yaml.org,2002:js/function', { | 
|   kind: 'scalar', | 
|   resolve: resolveJavascriptFunction, | 
|   construct: constructJavascriptFunction, | 
|   predicate: isFunction, | 
|   represent: representJavascriptFunction | 
| }); |