Skip to content

Commit

Permalink
fix: Support ES2015+ function definitions in function#toStringTokens()
Browse files Browse the repository at this point in the history
Additionally revert from problematic regex based implementation. Addresses #21
  • Loading branch information
medikoo committed Feb 21, 2024
1 parent 3551cdd commit a52e957
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 13 deletions.
57 changes: 46 additions & 11 deletions function/#/to-string-tokens.js
@@ -1,17 +1,52 @@
"use strict";

var validFunction = require("../valid-function");
var isValue = require("../../object/is-value")
, esniff = require("esniff")
, validFunction = require("../valid-function");

var re1 = /^\s*function[\0-')-\uffff]*\(([\0-(*-\uffff]*)\)\s*\{([\0-\uffff]*)\}\s*$/
, re2 = /^\s*\(?([\0-'*-\uffff]*)\)?\s*=>\s*(\{?[\0-\uffff]*\}?)\s*$/;
var classRe = /^\s*class[\s{/}]/;

module.exports = function () {
var str = String(validFunction(this)), data = str.match(re1);
if (!data) {
data = str.match(re2);
if (!data) throw new Error("Unrecognized string format");
data[1] = data[1].trim();
if (data[2][0] === "{") data[2] = data[2].trim().slice(1, -1);
}
return { args: data[1], body: data[2] };
var str = String(validFunction(this));
if (classRe.test(str)) throw new Error("Class methods are not supported");

var argsStartIndex
, argsEndIndex
, bodyStartIndex
, bodyEndReverseIndex = -1
, shouldTrimArgs = false;

esniff(str, function (emitter, accessor) {
emitter.once("trigger:(", function () { argsStartIndex = accessor.index + 1; });
emitter.once("trigger:=", function () {
if (isValue(argsStartIndex)) return;
argsStartIndex = 0;
argsEndIndex = accessor.index;
shouldTrimArgs = true;
if (!accessor.skipCodePart("=>")) {
throw new Error("Unexpected function string: " + str);
}
accessor.skipWhitespace();
if (!accessor.skipCodePart("{")) bodyEndReverseIndex = Infinity;
bodyStartIndex = accessor.index;
});
emitter.on("trigger:)", function () {
if (accessor.scopeDepth) return;
argsEndIndex = accessor.index;
accessor.skipCodePart(")");
accessor.skipWhitespace();
if (accessor.skipCodePart("=>")) {
accessor.skipWhitespace();
if (!accessor.skipCodePart("{")) bodyEndReverseIndex = Infinity;
} else if (!accessor.skipCodePart("{")) {
throw new Error("Unexpected function string: " + str);
}
bodyStartIndex = accessor.index;
accessor.stop();
});
});

var argsString = str.slice(argsStartIndex, argsEndIndex);
if (shouldTrimArgs) argsString = argsString.trim();
return { args: argsString, body: str.slice(bodyStartIndex, bodyEndReverseIndex) };
};
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -25,6 +25,7 @@
"dependencies": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
"esniff": "^2.0.1",
"next-tick": "^1.1.0"
},
"devDependencies": {
Expand Down
9 changes: 7 additions & 2 deletions test/function/#/to-string-tokens.js
Expand Up @@ -10,10 +10,10 @@ module.exports = function (t, a) {
a.deep(t.call(function () {}), { args: "", body: "" });
// eslint-disable-next-line no-unused-vars
a.deep(t.call(function (raz) {}), { args: "raz", body: "" });
a.deep(t.call(function () { Object(); }), { args: "", body: " Object(); " });
a.deep(t.call(function () { return {}; }), { args: "", body: " return {}; " });

try {
eval("(() => {})");
eval("((foo = bar) => {})");
} catch (e) {
// Non ES2015 env
return;
Expand All @@ -23,4 +23,9 @@ module.exports = function (t, a) {
a.deep(t.call(eval("((elo) => foo)")), { args: "elo", body: "foo" });
a.deep(t.call(eval("(elo => foo)")), { args: "elo", body: "foo" });
a.deep(t.call(eval("((elo, bar) => foo())")), { args: "elo, bar", body: "foo()" });
a.deep(t.call(eval("foo=>bar")), { args: "foo", body: "bar" });
a.deep(t.call(eval("(foo = { marko: (elo) => { someFunct(); } }) => { body(); }")), {
args: "foo = { marko: (elo) => { someFunct(); } }",
body: " body(); "
});
};

0 comments on commit a52e957

Please sign in to comment.