UNPKG

func-args

Version:

ECMAScript Function Arguments parser, Get arguments of a function, useful for and used in dependency injectors. Works for regular functions, generator functions and arrow functions.

153 lines (120 loc) 2.84 kB
/** * Created by user on 2018/6/4/004. */ import * as acorn from 'acorn'; import * as ESTree from 'estree'; import { ArrowFunctionExpression, FunctionExpression } from 'estree'; import { IParams, _IParams, parseFnParams, toValues } from './params'; export * from './params'; export const SUPPORT_FUNCTION_TO_STRING = /\{ \[native code\] \}$/.test(toString(Math.abs)); export interface IParseFunc { type: "FunctionExpression" | "ArrowFunctionExpression"; name: string; native: boolean; generator: boolean; async: boolean; args: (string | string[] | { [k: string]: string; } | _IParams[])[]; params: string[]; source: string; } export function parse(fn, allowNative?: boolean, options?: acorn.Options): IParseFunc export function parse(fn, options?: acorn.Options, allowNative?: boolean): IParseFunc export function parse(fn, options?, allowNative?): IParseFunc { let source = toString(fn, true); if (typeof options === 'boolean') { [options, allowNative] = [allowNative, options]; } options = Object.assign({ ecmaVersion: 8, } as acorn.Options, options) as acorn.Options; let native = false; let _ast; try { // @ts-ignore _ast = acorn.parse(source, options).body[0].expression } catch (e) { source = toString(fn); //console.log(source); if (/\{ \[native code\] \}$/.test(source)) { native = true; if (allowNative) { source = source.replace(/\{ \[native code\] \}$/, '{}'); } } try { // @ts-ignore _ast = acorn.parse(source).body[0].expression } catch (e) { if (native && allowNative) { } else { throw e; } } } let ast: ReturnType<typeof fnType>; let args: ReturnType<typeof parseFnParams> = []; if (_ast) { ast = fnType(_ast); args = parseFnParams(ast.params); // console.dir(ast, { // depth: 1 // }); } else { // @ts-ignore ast = {}; } return { type: ast.type, name: fn.name, native, generator: ast.generator, async: ast.async, args, params: toValues(args), source: toString(fn), } as IParseFunc; } export function toString(fn, wrap?: boolean): string { let s = Function.prototype.toString.call(fn); if (wrap) s = '(' + s + ')'; return s; } export function fnType<T extends ESTree.Function>(ast: T) { if (ast.type == 'ArrowFunctionExpression') { return ast as ESTree.ArrowFunctionExpression } else if (ast.type == 'FunctionExpression') { return ast as ESTree.FunctionExpression } throw new TypeError(`Expected an Function but got ${ast.type}.`) } export function parseFunc(fn, allowNative?: boolean, options?: acorn.Options): IParseFunc export function parseFunc(fn, options?: acorn.Options, allowNative?: boolean): IParseFunc export function parseFunc(fn, options?, allowNative?): IParseFunc { return parse(fn, options, allowNative); } export default parse