Skip to content

Instantly share code, notes, and snippets.

@dfkaye
Last active June 30, 2022 04:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dfkaye/c50ff265f4411145151fff2f44c2e1bf to your computer and use it in GitHub Desktop.
Save dfkaye/c50ff265f4411145151fff2f44c2e1bf to your computer and use it in GitHub Desktop.
parse body of a function given constraints
// 24 June 2022
// parse the body of a function if its only parameter is self
// 25 june 2022
// - added full body test,
// - fixed trailing brace regexp (missing $).
// 29 June 2022
// - append semi-colon and linebreak to each parsed function body, to enable
// concatenating multiple functions in the next post, "communicating embedded
// worker factories" at
// https://gist.github.com/dfkaye/c6d77fde86aea70ef6ae79bda2219582
// ...companion to "parse parameter names from function argument list"
// at https://gist.github.com/dfkaye/51550ec0818e507aebd89a585b2c05c4
// ...continued from "import an embedded worker within another embedded worker"
// at https://gist.github.com/dfkaye/20ff0934cd8d2b0fa7aea5606ac7ab89
// Self() is a special purpose function meant to extract a stringified function
// body for use as an embedded worker script, loaded as a blob with an object
// URL.
// Self() extracts the body of a function argument if:
// 1. it has only one argument,
// 2. the argument is `self` or has a `self` property defined (i.e., `self` is
// not a fallback, as in `( self = "value" )`, e.g.),
// 3. it's an arrow function, and
// 3.1 parentheses surround the function argument,
// 3.2 braces surround the function body.
// Self() is meant to extract a stringified function body for use as an embedded
// worker script, loaded as a blob with an object URL.
function Self(fn) {
var fs = String(fn).trim();
var parseable = typeof fn == "function"
&& fn.length === 1
&& fs.match(/(self)[^\)]*\)[^\{]*\{/);
if (!parseable) {
return;
}
return fs /* .substring(fs.indexOf("self") + 4) */
.replace(/(self)?[^\)]*\)[^\{]*\{/, '')
.replace(/\s*\}\s*$/, '')
.split("\n")
.filter(s => /\S/.test(s))
.join("\n")
.concat(";\n");
}
/* test it out */
console.group("* failing *");
[
function Named (param) { console.log( "named" ); },
function (param) { console.log( "anonymous" ); },
function Named ( { param = "function" }) { console.log( "named:param" ); },
function ( { param = "function" }) { console.log( "anonymous:param" ); },
param => "arrow",
( { param = "arrow"} ) => "arrow:param",
( { param = "arrow"} ) => { "arrow:braces" },
self => "arrow:no-braces",
self => { "arrow:braces:no-parens" },
( self = "arrow" ) => { "arrow:parens:fallback" }
].forEach(fn => {
console.log(Self(fn))
});
console.groupEnd("* failing *");
console.group("** passing **");
[
function (self) { console.log( "anonymous:self" ); },
function Named (self) { console.log( "named:self" ); },
( self ) => {
console.log( "arrow:self" );
},
function Named ( { self = "function" } ) { console.log( "named:self:param" ); },
function ( { self = "function" } ) { console.log( "anonymous:self:param" ); },
( { self = "arrow" } ) => {
console.log("arrow:self:param");
}
].forEach(fn => {
console.log(Self(fn))
});
console.groupEnd("** passing **");
console.group("*** fullbody ***");
function FullBody(self) {
// full body script test
function credentials({ sender, address }) {
return address === self.location
&& senders.has(sender)
}
self.senders = new Set();
self.init = function(data) {
senders.has(data.sender) || senders.add(data.sender);
return credentials(data);
}
self.onmessage = function (request) {
var data = Object(request.data);
console.warn(data.sender, data.address, data.action, data.value);
if (data.action === 'init') {
self.init(data);
}
var response = Object.assign({}, data);
self.postMessage(response);
}
}
console.log(
Self( FullBody )
);
console.groupEnd("*** fullbody ***");
/*
* failing *
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
** passing **
console.log( "anonymous:self" ); debugger eval code:83:11
console.log( "named:self" ); debugger eval code:83:11
console.log( "arrow:self" ); debugger eval code:83:11
console.log( "named:self:param" ); debugger eval code:83:11
console.log( "anonymous:self:param" ); debugger eval code:83:11
console.log("arrow:self:param");
*** full body ***
// full body script test
function credentials({ sender, address }) {
return address === self.location
&& senders.has(sender)
}
self.senders = new Set();
self.init = function(data) {
senders.has(data.sender) || senders.add(data.sender);
return credentials(data);
}
self.onmessage = function (request) {
var data = Object(request.data);
console.warn(data.sender, data.address, data.action, data.value);
if (data.action === 'init') {
self.init(data);
}
var response = Object.assign({}, data);
self.postMessage(response);
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment