Git Product home page Git Product logo

tunnckocore / parse-function Goto Github PK

View Code? Open in Web Editor NEW
37.0 5.0 6.0 1.04 MB

(!! moved to tunnckoCore/opensource multi-package repository !!) :trident: Parse a function into an object using espree, acorn or babylon parsers. Extensible through Smart Plugins.

Home Page: https://tunnckocore.com/opensource

License: MIT License

JavaScript 100.00%
parse parser javascript function es6 async-await plugins ast acorn babylon

parse-function's Introduction

Parse a function

parse-function npm version github release License

Parse a function into an object using espree, acorn or babylon parsers. Extensible through Smart Plugins

You might also be interested in hela.

Quality Assurance ๐Ÿ’ฏ

Code Style Standard Linux Build Code Coverage Dependencies Status Renovate App Status

If you have any how-to kind of questions, please read Code of Conduct and join the chat room or open an issue.
You may also read the Contributing Guide. There, beside "How to contribute?", we describe everything stated by the badges.

Make A Pull Request Code Format Prettier Conventional Commits Semantically Released Renovate App Status

Project is semantically & automatically released on CircleCI with new-release and its New Release Github Bot.

All Contributors Spec Newsletter Subscribe Give thanks Share Love Tweet NPM Downloads Weekly NPM Downloads Monthly NPM Downloads Total

Features

  • Always up-to-date: auto-publish new version when new version of dependency is out, Renovate
  • Standard: using StandardJS, Prettier, SemVer, Semantic Release and conventional commits
  • Smart Plugins: for extending the core API or the end Result, see .use method and Plugins Architecture
  • Extensible: using plugins for working directly on AST nodes, see the Plugins Architecture
  • ES2017 Ready: by using .parseExpression method of the babylon v7.x parser
  • Customization: allows switching the parser, through options.parse
  • Support for: arrow functions, default parameters, generators and async/await functions
  • Stable: battle-tested in production and against all parsers - espree, acorn, babylon
  • Tested: with 450+ tests for 200% coverage

Table of Contents

(TOC generated by verb using markdown-toc)

Install

This project requires Node.js v6 and above. Use yarn v1 / npm v5 or above to install it.

$ yarn add parse-function

Which version to use?

There's no breaking changes between the v2.x version. The only breaking is v2.1 which also is not working properly, so no use it.

Use v2.0.x

When you don't need support for arrow functions and es6 default params. This version uses a RegExp expression to work.

Use v2.2.x

Only when you need a basic support for es6 features like arrow functions. This version uses a RegExp expression to work.

Use v2.3.x

When you want full* support for arrow functions and es6 default params. Where this "full", means "almost full", because it has bugs. This version also uses (acorn.parse) real parser to do the parsing.

Use v3.x

When you want to use different parser instead of the default babylon.parse, by passing custom parse function to the options.parse option. From this version we require node >= 4.

Use v4.x

When you want full customization and most stable support for old and modern features. This version uses babylon.parseExpression for parsing and provides a Plugins API. See the Features section for more info.

Use v5.x

It is basically the same as v4, but requires Node 6 & npm 5. Another is boilerplate stuff.

back to top

Notes

Throws in one specific case

see: issue #3 and test/index.js#L229-L235

It may throw in one specific case, otherwise it won't throw, so you should relay on the result.isValid for sure.

Function named "anonymous"

see: test/index.js#L319-L324 and Result section

If you pass a function which is named "anonymous" the result.name will be 'anonymous', but the result.isAnonymous will be false and result.isNamed will be true, because in fact it's a named function.

Real anonymous function

see: test/index.js#L326-L331 and Result section

Only if you pass really an anonymous function you will get result.name equal to null, result.isAnonymous equal to true and result.isNamed equal to false.

back to top

Plugins Architecture

see: the .use method, test/index.js#L305-L317 and test/index.js#L396-L414

A more human description of the plugin mechanism. Plugins are synchronous - no support and no need for async plugins here, but notice that you can do that manually, because that exact architecture.

The first function that is passed to the .use method is used for extending the core API, for example adding a new method to the app instance. That function is immediately invoked.

const parseFunction = require('parse-function')
const app = parseFunction()

app.use((self) => {
  // self is same as `app`
  console.log(self.use)
  console.log(self.parse)
  console.log(self.define)

  self.define(self, 'foo', (bar) => bar + 1)
})

console.log(app.foo(2)) // => 3

On the other side, if you want to access the AST of the parser, you should return a function from that plugin, which function is passed with (node, result) signature.

This function is lazy plugin, it is called only when the .parse method is called.

const parseFunction = require('parse-function')
const app = parseFunction()

app.use((self) => {
  console.log('immediately called')

  return (node, result) => {
    console.log('called only when .parse is invoked')
    console.log(node)
    console.log(result)
  } 
})

Where 1) the node argument is an object - actual and real AST Node coming from the parser and 2) the result is an object too - the end Result, on which you can add more properties if you want.

back to top

API

Review carefully the provided examples and the working tests.

Initializes with optional opts object which is passed directly to the desired parser and returns an object with .use and .parse methods. The default parse which is used is babylon's .parseExpression method from v7.

Params

  • opts {Object}: optional, merged with options passed to .parse method
  • returns {Object} app: object with .use and .parse methods

Example

const parseFunction = require('parse-function')

const app = parseFunction({
  ecmaVersion: 2017
})

const fixtureFn = (a, b, c) => {
  a = b + c
  return a + 2
}

const result = app.parse(fixtureFn)
console.log(result)

// see more
console.log(result.name) // => null
console.log(result.isNamed) // => false
console.log(result.isArrow) // => true
console.log(result.isAnonymous) // => true

// array of names of the arguments
console.log(result.args) // => ['a', 'b', 'c']

// comma-separated names of the arguments
console.log(result.params) // => 'a, b, c'

Parse a given code and returns a result object with useful properties - such as name, body and args. By default it uses Babylon parser, but you can switch it by passing options.parse - for example options.parse: acorn.parse. In the below example will show how to use acorn parser, instead of the default one.

Params

  • code {Function|String}: any kind of function or string to be parsed
  • options {Object}: directly passed to the parser - babylon, acorn, espree
  • options.parse {Function}: by default babylon.parseExpression, all options are passed as second argument to that provided function
  • returns {Object} result: see result section for more info

Example

const acorn = require('acorn')
const parseFn = require('parse-function')
const app = parseFn()

const fn = function foo (bar, baz) { return bar * baz }
const result = app.parse(fn, {
  parse: acorn.parse,
  ecmaVersion: 2017
})

console.log(result.name) // => 'foo'
console.log(result.args) // => ['bar', 'baz']
console.log(result.body) // => ' return bar * baz '
console.log(result.isNamed) // => true
console.log(result.isArrow) // => false
console.log(result.isAnonymous) // => false
console.log(result.isGenerator) // => false

Add a plugin fn function for extending the API or working on the AST nodes. The fn is immediately invoked and passed with app argument which is instance of parseFunction() call. That fn may return another function that accepts (node, result) signature, where node is an AST node and result is an object which will be returned result from the .parse method. This retuned function is called on each node only when .parse method is called.

See Plugins Architecture section.

Params

  • fn {Function}: plugin to be called
  • returns {Object} app: instance for chaining

Example

// plugin extending the `app`
app.use((app) => {
  app.define(app, 'hello', (place) => `Hello ${place}!`)
})

const hi = app.hello('World')
console.log(hi) // => 'Hello World!'

// or plugin that works on AST nodes
app.use((app) => (node, result) => {
  if (node.type === 'ArrowFunctionExpression') {
    result.thatIsArrow = true
  }
  return result
})

const result = app.parse((a, b) => (a + b + 123))
console.log(result.name) // => null
console.log(result.isArrow) // => true
console.log(result.thatIsArrow) // => true

const result = app.parse(function foo () { return 123 })
console.log(result.name) // => 'foo'
console.log(result.isArrow) // => false
console.log(result.thatIsArrow) // => undefined

Define a non-enumerable property on an object. Just a convenience mirror of the define-property library, so check out its docs. Useful to be used in plugins.

Params

  • obj {Object}: the object on which to define the property
  • prop {String}: the name of the property to be defined or modified
  • val {Any}: the descriptor for the property being defined or modified
  • returns {Object} obj: the passed object, but modified

Example

const parseFunction = require('parse-function')
const app = parseFunction()

// use it like `define-property` lib
const obj = {}
app.define(obj, 'hi', 'world')
console.log(obj) // => { hi: 'world' }

// or define a custom plugin that adds `.foo` property
// to the end result, returned from `app.parse`
app.use((app) => {
  return (node, result) => {
    // this function is called
    // only when `.parse` is called

    app.define(result, 'foo', 123)

    return result
  }
})

// fixture function to be parsed
const asyncFn = async (qux) => {
  const bar = await Promise.resolve(qux)
  return bar
}

const result = app.parse(asyncFn)

console.log(result.name) // => null
console.log(result.foo) // => 123
console.log(result.args) // => ['qux']

console.log(result.isAsync) // => true
console.log(result.isArrow) // => true
console.log(result.isNamed) // => false
console.log(result.isAnonymous) // => true

back to top

Result

In the result object you have name, args, params, body and few hidden properties that can be useful to determine what the function is - arrow, regular, async/await or generator.

  • name {String|null}: name of the passed function or null if anonymous
  • args {Array}: arguments of the function
  • params {String}: comma-separated list representing the args
  • defaults {Object}: key/value pairs, useful when use ES2015 default arguments
  • body {String}: actual body of the function, respects trailing newlines and whitespaces
  • isValid {Boolean}: is the given value valid or not, that's because it never throws!
  • isAsync {Boolean}: true if function is ES2015 async/await function
  • isArrow {Boolean}: true if the function is arrow function
  • isNamed {Boolean}: true if function has name, or false if is anonymous
  • isGenerator {Boolean}: true if the function is ES2015 generator function
  • isAnonymous {Boolean}: true if the function don't have name

back to top

Related

Contributing

Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.
Please read the Contributing Guide and Code of Conduct documents for advices.

Author

License

Copyright ยฉ 2016, 2018, Charlike Mike Reagent. Released under the MIT License.


This file was generated by verb-generate-readme, v0.6.0, on March 05, 2018.
Project automation and management with hela task framework.

parse-function's People

Contributors

greenkeeperio-bot avatar renovate-bot avatar renovate[bot] avatar tootallnate avatar tunnckocore avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

parse-function's Issues

Announcement (a bit late): moved to a `tunnckoCore/opensource` monorepo

Since the last GitHub Release (tag, npm version) here which is 5.2.11 & 5.2.12 the project has moved to https://github.com/tunnckoCore/opensource at packages (or @packages) workspace. Please open PRs and issues there, the npm package is also is pointing to the correct location.

Any minor & patch version from those until the v6 (which is in the works at tunnckoCore/opensource#67) are just misc stuff and nothing important - they are because the monorepo stuff and maintenance, but nothing special to the codebase or any meaningful changes impacting you. In addition, there may be some broken versions that are missing dist files and such. Just upgrade to the latest version.


todo (for me): move the issues there

Error parsing class method

I've run into a strange edge case on the most recent version trying to parse a class method that contains an arrow function. Here is a minimal example:

const parseFunction = require('parse-function');
const app = parseFunction({ecmaVersion: 2017});

class A {
  func () {
    return () => 0;
  }
}

const a = new A();
var p = app.parse(a.func);
console.log(p.args);

This results in

./node_modules/parse-function/node_modules/babylon/lib/index.js:4335
  throw err;
  ^

SyntaxError: Unexpected token (1:7)
    at Parser.pp$5.raise (./node_modules/parse-function/node_modules/babylon/lib/index.js:4332:13)
    at Parser.pp.unexpected (./node_modules/parse-function/node_modules/babylon/lib/index.js:1689:8)
    at Parser.pp$3.getExpression (./node_modules/parse-function/node_modules/babylon/lib/index.js:3178:10)
    at Object.parseExpression (./node_modules/parse-function/node_modules/babylon/lib/index.js:6982:17)
    at Object.getNode (./node_modules/parse-function/lib/utils.js:90:18)
    at Object.parse (./node_modules/parse-function/index.js:126:24)
    at Object.<anonymous> (./class_method.js:12:13)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)

Removing the arrow function, it works as expected.

I'm not sure if this is a babylon bug or not because the string representation of the function is

func() {
    return () => 0;
  }

which I don't think is a valid expression on its own. This can be worked around by catching the error and trying again with 'function ' + fn.toString(), but I'm not sure if that's the best approach. I can create an issue upstream if you think it would be more appropriate to fix there.

Arrow function with inner function fails to parse

The following snippet fails to parse because result.value is erroneously(?) wrapped in { ... } on line https://github.com/tunnckoCoreLabs/parse-function/blob/master/src/index.js#L119-L121

import parseFunction from 'parse-function'
parseFunction().parse(arg => new Promise(resolve => {
    function inner() {}
    inner()
}))

babylon / @babel/parser throws the following error:

    SyntaxError: Unexpected token, expected "," (1:6)

      at Parser.raise (node_modules/babylon/lib/index.js:776:15)
      at Parser.unexpected (node_modules/babylon/lib/index.js:2079:16)
      at Parser.expect (node_modules/babylon/lib/index.js:2067:28)
      at Parser.parseObj (node_modules/babylon/lib/index.js:3465:14)
      at Parser.parseExprAtom (node_modules/babylon/lib/index.js:3123:21)
      at Parser.parseExprSubscripts (node_modules/babylon/lib/index.js:2757:21)
      at Parser.parseMaybeUnary (node_modules/babylon/lib/index.js:2736:21)
      at Parser.parseExprOps (node_modules/babylon/lib/index.js:2643:21)
      at Parser.parseMaybeConditional (node_modules/babylon/lib/index.js:2615:21)
      at Parser.parseMaybeAssign (node_modules/babylon/lib/index.js:2562:21)

Maybe just add isArrow to the if on line 119? Or might that cause problems with arrow functions in normal function bodies because the includes('=>') is too greedy and should only look at the start?

`args` and `arguments` confusion?

Maybe this is confusing. We have one more word params.

  • parameters to be arguments as array, and params for shorter alias
  • arguments to be arguments as string, and args for shorter alias

ES2015+ Support

Hello tunnckoCore,

I am currently using parse-function to extract function parameters in "gulp-di". Under certain circumstances, it might not support ES2015+ code, as its dependency parse-function seems currently to be limited to ES5 function declarations.

Gulp can be used in conjunction with ES2015 code in two ways:

  1. Writing ES2015+ code - the "gulpfile.js" would be written in ES2015+, as Node.js supports already a subset of the new standard.
  2. Writing ES2015+ code using the "Babel" transpiler - the "gulpfile.babel.js" and all imported modules would be transpiled back to ES5 code. In this case, parse-function would work as intended.

Do you plan adding support for the new standard?

I am currently experimenting with replacing parse-function with ECMAScript parsers like acorn or esprima, but it seems like an overkill to me.

The following links might be useful:

Weekly Digest (17 February, 2019 - 24 February, 2019)

Here's the Weekly Digest for tunnckoCoreLabs/parse-function:

ISSUES

This week, no issues have been created or closed.

PULL REQUESTS

This week, no pull requests has been proposed by the users.

CONTRIBUTORS

This week, no user has contributed to this repository.

STARGAZERS

This week, ik5 has starred the repository.
You are the star! โญ

COMMITS

This week, there have been no commits.

RELEASES

This week, no releases were published.

That's all for this week, please watch ๐Ÿ‘€ and star โญ tunnckoCoreLabs/parse-function to receive next weekly updates. ๐Ÿ˜ƒ

Strange parser error when an `if` statement is at the top of an async arrow function

Apologies if this is not a bug in parse-function itself, but I've tried this with all 3 recommended AST parsers and they all exhibit the same problem.

A parser error is thrown when an async arrow function has an if statement at the top. Ex:

$ cat t.js
const parser = require('parse-function')()

const fn = async (req, res) => {
  if (req) {}
}

console.log(parser.parse(fn));

$ node t
/test/node_modules/parse-function/node_modules/babylon/lib/index.js:812
    throw err;
    ^

SyntaxError: Unexpected token, expected { (1:19)

Strangely, the same error is thrown even if the if statement is commented out!

$ cat t.js
const parser = require('parse-function')()

const fn = async (req, res) => {
  //if (req) {}
}

console.log(parser.parse(fn));

$ node t
/test/node_modules/parse-function/node_modules/babylon/lib/index.js:812
    throw err;
    ^

SyntaxError: Unexpected token, expected { (1:19)

Now, it works if I remove the if statement:

$ cat t.js
const parser = require('parse-function')()

const fn = async (req, res) => {
}

console.log(parser.parse(fn));

$ node t
{ name: null,
  body: '\n',
  args: [ 'req', 'res' ],
  params: 'req, res' }

It also works if I change it to a regular async function instead of an arrow function:

$ cat t.js
const parser = require('parse-function')()

const fn = async function (req, res) {
  if (req) {}
}

console.log(parser.parse(fn));

$ node t
{ name: null,
  body: '\n  if (req) {}\n',
  args: [ 'req', 'res' ],
  params: 'req, res' }

So, strange behavior to say the least. Or maybe I'm doing something dumb. V8 at least has no problem parsing any of these versions. Thanks in advance for any support!

comments in parameters

Just wondering if this library has any problems when parsing comments in args like so:

 this.it('does throw part 1', function (/*done*/) {

thanks

Ensure dist builds exists

for the v5 releases.

all this problems will disappear on v6, which also will require node 8.6+, npm 5.2+

Low-prio: failing when something after CLOSE_CURLY

e.g.

var parseFunction = require('parse-function')
var fnStr = 'function (a) {return a}; var b = 1'
var data = parseFunction(fnStr)

console.log(data.body) // => 'return a}; var b = ' instead of 'return a'

resolved locally

Weekly Digest (3 March, 2019 - 10 March, 2019)

Here's the Weekly Digest for tunnckoCoreLabs/parse-function:


ISSUES

Last week, no issues were created.


PULL REQUESTS

Last week, no pull requests were created, updated or merged.


COMMITS

Last week there were no commits.


CONTRIBUTORS

Last week there were no contributors.


STARGAZERS

Last week there were no stargazers.


RELEASES

Last week there were no releases.


That's all for last week, please ๐Ÿ‘€ Watch and โญ Star the repository tunnckoCoreLabs/parse-function to receive next weekly updates. ๐Ÿ˜ƒ

You can also view all Weekly Digests by clicking here.

Your Weekly Digest bot. ๐Ÿ“†

Error when parsing a native function

Consider the following code:

const parseFunction = require('parse-function');
let app  = parseFunction();

console.warn(app.parse(Math.abs));

This throws an exception SyntaxError: Unexpected token, expected , (1:25) coming from babylon:

SyntaxError: Unexpected token, expected , (1:25)
    at Parser.raise (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:808:15)
    at Parser.unexpected (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:2185:16)
    at Parser.expect (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:2171:28)
    at Parser.parseExprList (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:3971:14)
    at Parser.parseExprAtom (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:3266:30)
    at Parser.parseExprSubscripts (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:2945:21)
    at Parser.parseMaybeUnary (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:2923:21)
    at Parser.parseExprOps (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:2828:21)
    at Parser.parseMaybeConditional (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:2798:21)
    at Parser.parseMaybeAssign (/home/ericmorand/Projects/twing/node_modules/babylon/lib/index.js:2757:21)

Is this an expected behavior? Is it possible to parse native functions?

Parse bound functions

reproduce:

const parser = require('parse-function')();

const foo = function foo() { return this.message; };
parser.parse(foo.bind({ message: 'hello' }))

error:

SyntaxError: Unexpected token, expected , (1:22)
      at Parser.raise (node_modules/parse-function/node_modules/babylon/lib/index.js:807:15)
      at Parser.unexpected (node_modules/parse-function/node_modules/babylon/lib/index.js:2108:16)
      at Parser.expect (node_modules/parse-function/node_modules/babylon/lib/index.js:2094:28)
      at Parser.parseExprList (node_modules/parse-function/node_modules/babylon/lib/index.js:3884:14)
      at Parser.parseExprAtom (node_modules/parse-function/node_modules/babylon/lib/index.js:3185:30)
      at Parser.parseExprSubscripts (node_modules/parse-function/node_modules/babylon/lib/index.js:2864:21)
      at Parser.parseMaybeUnary (node_modules/parse-function/node_modules/babylon/lib/index.js:2842:21)
      at Parser.parseExprOps (node_modules/parse-function/node_modules/babylon/lib/index.js:2751:21)
      at Parser.parseMaybeConditional (node_modules/parse-function/node_modules/babylon/lib/index.js:2721:21)
      at Parser.parseMaybeAssign (node_modules/parse-function/node_modules/babylon/lib/index.js:2680:21)
      at Parser.parseExpression (node_modules/parse-function/node_modules/babylon/lib/index.js:2634:21)
      at Parser.parseStatementContent (node_modules/parse-function/node_modules/babylon/lib/index.js:4157:21)
      at Parser.parseStatement (node_modules/parse-function/node_modules/babylon/lib/index.js:4045:17)
      at Parser.parseBlockOrModuleBlockBody (node_modules/parse-function/node_modules/babylon/lib/index.js:4590:23)
      at Parser.parseBlockBody (node_modules/parse-function/node_modules/babylon/lib/index.js:4576:10)
      at Parser.parseBlock (node_modules/parse-function/node_modules/babylon/lib/index.js:4565:10)
      at Parser.parseFunctionBody (node_modules/parse-function/node_modules/babylon/lib/index.js:3814:24)
      at Parser.parseFunctionBodyAndFinish (node_modules/parse-function/node_modules/babylon/lib/index.js:3792:10)
      at Parser.parseFunction (node_modules/parse-function/node_modules/babylon/lib/index.js:4717:10)
      at Parser.parseFunctionExpression (node_modules/parse-function/node_modules/babylon/lib/index.js:3259:17)
      at Parser.parseExprAtom (node_modules/parse-function/node_modules/babylon/lib/index.js:3193:21)
      at Parser.parseExprSubscripts (node_modules/parse-function/node_modules/babylon/lib/index.js:2864:21)
      at Parser.parseMaybeUnary (node_modules/parse-function/node_modules/babylon/lib/index.js:2842:21)
      at Parser.parseExprOps (node_modules/parse-function/node_modules/babylon/lib/index.js:2751:21)
      at Parser.parseMaybeConditional (node_modules/parse-function/node_modules/babylon/lib/index.js:2721:21)
      at Parser.parseMaybeAssign (node_modules/parse-function/node_modules/babylon/lib/index.js:2680:21)
      at Parser.parseExpression (node_modules/parse-function/node_modules/babylon/lib/index.js:2634:21)
      at Parser.getExpression (node_modules/parse-function/node_modules/babylon/lib/index.js:2609:21)
      at Object.parseExpression (node_modules/parse-function/node_modules/babylon/lib/index.js:10203:17)
      at Object.getNode (node_modules/parse-function/dest/index.js:91:18)
      at Object.parse (node_modules/parse-function/dest/index.js:367:24)
      at Context.it.only (lib/rodar.spec.js:27:14)

ES6 default parameters

Default parameters are not currently supported:

> parseFunction('function (opts = { foo: { done: (x) => console.log({ value: x }) } }, cb) { /* ... */ }')
{ name: 'anonymous',
  body: ' foo: { done: (x) => console.log({ value: x }) } }, cb) { /* ... */ ',
  args: [ 'opts' ],
  params: 'opts' }

I would expect something like this:

{ name: 'anonymous',
  body: ' /* ... */ ',
  args: [ 'opts', 'cb' ],
  params: 'opts = { foo: { done: (x) => console.log({ value: x }) } }, cb' }

But perhaps it's even better to capture default params instead of throwing them away:

{ name: 'anonymous',
  body: '  /* ... */ ',
  args: [ 'opts', 'cb' ],
  params: 'opts = { foo: { done: (x) => console.log({ value: x }) } }, cb',
  defaults: {
    opts: '{ foo: { done: (x) => console.log({ value: x }) } }'
  } }

v5.1.3 doesn't have a `dist/index.js` file

And thus is broken:

000 โ–ฒ 102 -4 โ†’ ~ (master) $ npm i parse-function
+ [email protected]
added 9 packages in 2.807s

000 โ–ฒ 102 -4 โ†’ ~ (master) $ node
> require('parse-function')
Error: Cannot find module 'parse-function'
    at Function.Module._resolveFilename (module.js:555:15)
    at Function.Module._load (module.js:482:25)
    at Module.require (module.js:604:17)
    at require (internal/module.js:11:18)

Weekly Digest (24 February, 2019 - 3 March, 2019)

Here's the Weekly Digest for tunnckoCoreLabs/parse-function:


ISSUES

Last week, no issues were created.


PULL REQUESTS

Last week, no pull requests were created, updated or merged.


COMMITS

Last week there were no commits.


CONTRIBUTORS

Last week there were no contributors.


STARGAZERS

Last week there were no stargazers.


RELEASES

Last week there were no releases.


That's all for last week, please ๐Ÿ‘€ Watch and โญ Star the repository tunnckoCoreLabs/parse-function to receive next weekly updates. ๐Ÿ˜ƒ

You can also view all Weekly Digests by clicking here.

Your Weekly Digest bot. ๐Ÿ“†

ES6 features

Hey, I'm trying to use some ES6 standards, which should be supported according to the readme.

const parseFunction = require('parse-function');

function a({
    a = null,
    b = null,
    c = null
}) {
    console.log('a', a, b, c);
}

const b = ({a=null, b=null, c}, d, {e=null, m=12} = {}, f) => {
    console.log('b', a, b, c);
};

const c = () => {
    console.log('c');
};

function d() {
    console.log('d');
}

function e(a) {
    console.log('e', a);
}

console.log(parseFunction(a));
console.log(parseFunction(b));
console.log(parseFunction(c));
console.log(parseFunction(d));
console.log(parseFunction(e));

Class methods

Parsing class methods seems to yield empty bodies, anonymous names and empty arg lists.

Example:

'use strict';

var parseFunction = require('parse-function');

class EqualityChecker {
    isEqual(a, b) {
        return a === b;
    }
}

var checker = new EqualityChecker();
console.log('Prototype:', parseFunction(EqualityChecker.prototype.isEqual));
console.log('Instance:', parseFunction(checker.isEqual));

Both console.logs will print { name: 'anonymous', args: [], params: '', body: '' }.

I suspect it is because .toString() on methods returns the exact representation from the code, from the first to the last token, so in our case (tabs originally in the string):

isEqual(a, b) {
                return a === b;
        }

The same problem occurs with this compacted ES6 "function-less" notation:

parseFunction({
    isEqual(a, b) {
        return a === b;
    }
}.isEqual)

Breaks on destructured args

> const parseFn = require('parse-function')
> const app = parseFn({ ecmaVersion: 2017 })
> const b = ({a, b, c}) => a + b + c
undefined
> app.parse(b)
{ name: null,
  body: 'a + b + c',
  args: [ false ],
  params: 'false' }

Any plans on incorporating this in the future?

Node: 8.1.4

hints and ideas for improving

ref #5 #4 and #2

We should detect that there's new line and mark that fact, then we can detect of ch is after some comment opening like // or /*.. and hm.

Okey. Other approach can be using snapdragon, but we strongly need benchmark tests first before any steps forward.

//cc @eush77 @cmtt

Destructuring

Yo, how hard would it be to make this package understand destructuring?

({ foo, bar = 5 }) => null

Wanted to ask before trying to do it myself.

support for generator functions and async functions

Loving this lib so far, but it appears that it is not currently configured to parse generator functions and async functions

function*

and async functions

async function(){

}

can this be confirmed and do you plan to update it if so? thanks!

Release v4

1) Plugins API - #27 (comment)
2) Some kind of fix for #27
3) Real anonymous functions will have result.name undefined and result.isAnonymous: true, where the functions named "anonymous" will have result.name === 'anonymous' and result.isAnonymous: false

V5.3.2 Error: Cannot find module './utils'

In @5.3.2 cjs/index.js throws the following error:

Error: Cannot find module './utils'
    at Function.Module._resolveFilename (module.js:548:15)
    at Function.Module._load (module.js:475:25)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (xxx/node_modules/parse-function/dist/cjs/index.js:1:731)

Seems doesn't bundle utils.js into index.js

Bound functions and other gibberish

Apparently, this is considered valid (at least on 2.3.1):

var parseFunction = require('parse-function');

function equals(a, b) {
    return a === b || (isNaN(a) && isNaN(b));
}
var boundEquals = equals.bind(global);

// Prints "true"
console.log(parseFunction(boundEquals).valid);

I'm not quite sure if this is the result everyone expects, given that the returned body is " [native code] ".
Even more mind-boggling is this:

parseFunction('function(a, b) { @(!)$!#$E+F#$+#%)$+#OOo.__ - + = = = + // }').valid

In which parallel universe can V8 execute this? The "valid" flag seems misleading. Might be worth adding some warnings to the README.

In particular, assuming " [native code] " is valid may be risky, since a user might not expect their argument information to go away after a .bind(). It may be better to consider unparseable function bodies as invalid as a whole, or provide a run-time flag to enable such behavior (so that the API remains compatible with whatever weird flavor of JS / JSX the user needs).

Weekly Digest (10 February, 2019 - 17 February, 2019)

Here's the Weekly Digest for tunnckoCoreLabs/parse-function:


ISSUES

Last week 1 issue was created.
It is still open.

OPEN ISSUES

๐Ÿ’š #174 Add license scan report and status, by fossabot

NOISY ISSUE

๐Ÿ”ˆ #174 Add license scan report and status, by fossabot
It received 2 comments.


PULL REQUESTS

Last week, 1 pull request was created, updated or merged.

UPDATED PULL REQUEST

Last week, 1 pull request was updated.
๐Ÿ’› #174 Add license scan report and status, by fossabot


COMMITS

Last week there were no commits.


CONTRIBUTORS

Last week there were no contributors.


STARGAZERS

Last week there were no stargazers.


RELEASES

Last week there were no releases.


That's all for last week, please ๐Ÿ‘€ Watch and โญ Star the repository tunnckoCoreLabs/parse-function to receive next weekly updates. ๐Ÿ˜ƒ

You can also view all Weekly Digests by clicking here.

Your Weekly Digest bot. ๐Ÿ“†

Functions containing GREATER_THAN are parsed incorrectly

> parseFunction(function (a, b) { return a > b })
{ name: 'anonymous',
  body: ' ',
  params: 'unction (a, b) { return ',
  args: [ 'unction (a', 'b) { return ' ] }

Functions that contain > character are loosely considered arrow functions in walk, and later in build function params and args properties are computed incorrectly because of that. I'm not sure how you would fix that.

Bug with arguments default value consisting of a list of expressions

Consider the following perfectly valid function:

function foo(a = (false, false, true)) {
    return a;
}

When called with no parameter, this function returns true.

Parsing it with parse-function...

const pf = require('parse-function');

let p = pf().parse(foo);

console.warn(p.defaults);

...return the following defaults:

{ a: 'false, false, true' }

The defaults should be:

{ a: 'true' }

benchmarks

maybe using benchmarked

Any PRs welcome, cuz don't have the time atm (for the next days)

Files missing in v4 release

After installing the latest release, I get the following

> require('parse-function')
Error: Cannot find module './lib/utils'
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.Module._load (module.js:417:25)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (node_modules/parse-function/index.js:14:15)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)

Inspecting node-modules/parse-function, the lib directory is not present.

$ ls node_modules/parse-function/
CHANGELOG.md  index.js  LICENSE  node_modules  package.json  README.md

v3

  • #18 last comment
  • #14
  • drop long name properties
  • allow both babylon or acorn to be used
  • allow loose parsing (that's because the function () {} cant be parsed if no acorn_loose)
  • allow options to be passed to babylon/acorn

Function with named parameters is not parsed correctly

I have code as below:

const parseFunction = require('parse-function');
const app = parseFunction({
  ecmaVersion: 2017
});

const result = app.parse(async ({ firstName, lastName }) => {
  console.log(`Received input at Server ${JSON.stringify(firstName)}`);
  return { 'Test': `Hi ${lastName}` };
});

console.log({result});

The result object looks like:


[[StableObjectId]]:2
args:Array(1) [false]
body:"\n  console.log(`Received input at Server ${JSON.stringify(firstName)}`);\n  return { 'Test': `Hi ${lastName}` };\n"
defaults:Object {false: undefined}
isAnonymous:true
isArrow:true
isAsync:true
isExpression:false
isGenerator:false
isNamed:false
isValid:true
name:null
params:"false"
value:"async ({ firstName, lastName }) => {\n  console.log(`Received input at Server ${JSON.stringify(firstName)}`);\n  return { 'Test': `Hi ${lastName}` };\n}"
__proto__:Object {constructor: , __defineGetter__: , __defineSetter__: , โ€ฆ}

params in output returns as false instead of firstName, lastName

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.