| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- '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
- });
|