e7b569a379b7e9a05e0ddf5a5522e3eff9f4c564cdc2129f70ed2093fcdbef23050e5bc11c241dc9def5b434e3857099df8c987bf9250556f889a82911f1a8 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. 'use strict';
  2. var esprima;
  3. // Browserified version does not have esprima
  4. //
  5. // 1. For node.js just require module as deps
  6. // 2. For browser try to require mudule via external AMD system.
  7. // If not found - try to fallback to window.esprima. If not
  8. // found too - then fail to parse.
  9. //
  10. try {
  11. // workaround to exclude package from browserify list.
  12. var _require = require;
  13. esprima = _require('esprima');
  14. } catch (_) {
  15. /*global window */
  16. if (typeof window !== 'undefined') esprima = window.esprima;
  17. }
  18. var Type = require('../../type');
  19. function resolveJavascriptFunction(data) {
  20. if (data === null) return false;
  21. try {
  22. var source = '(' + data + ')',
  23. ast = esprima.parse(source, { range: true });
  24. if (ast.type !== 'Program' ||
  25. ast.body.length !== 1 ||
  26. ast.body[0].type !== 'ExpressionStatement' ||
  27. ast.body[0].expression.type !== 'FunctionExpression') {
  28. return false;
  29. }
  30. return true;
  31. } catch (err) {
  32. return false;
  33. }
  34. }
  35. function constructJavascriptFunction(data) {
  36. /*jslint evil:true*/
  37. var source = '(' + data + ')',
  38. ast = esprima.parse(source, { range: true }),
  39. params = [],
  40. body;
  41. if (ast.type !== 'Program' ||
  42. ast.body.length !== 1 ||
  43. ast.body[0].type !== 'ExpressionStatement' ||
  44. ast.body[0].expression.type !== 'FunctionExpression') {
  45. throw new Error('Failed to resolve function');
  46. }
  47. ast.body[0].expression.params.forEach(function (param) {
  48. params.push(param.name);
  49. });
  50. body = ast.body[0].expression.body.range;
  51. // Esprima's ranges include the first '{' and the last '}' characters on
  52. // function expressions. So cut them out.
  53. /*eslint-disable no-new-func*/
  54. return new Function(params, source.slice(body[0] + 1, body[1] - 1));
  55. }
  56. function representJavascriptFunction(object /*, style*/) {
  57. return object.toString();
  58. }
  59. function isFunction(object) {
  60. return Object.prototype.toString.call(object) === '[object Function]';
  61. }
  62. module.exports = new Type('tag:yaml.org,2002:js/function', {
  63. kind: 'scalar',
  64. resolve: resolveJavascriptFunction,
  65. construct: constructJavascriptFunction,
  66. predicate: isFunction,
  67. represent: representJavascriptFunction
  68. });