So like you shouldn't use eval()
or the Function
constructor cause they can be security vulnerabilities for script injection. But what if you have to?
I previously used the Function
constructor for my GQLinJSX project. To take server-side parsed JSX and render the output, chef's kiss.
So webworkers cannot use ESM imports which sucks, but we have a couple of functions we want to use within the runpkg project, in this case a url parsing function. It looks something like the following:
const parseUrl = (url = window.location.search.slice(1).replace(/\/$/, "")) => {
const parts = url
.trim()
.replace("https://unpkg.com", "")
.split("/")
.map(part => part.trim())
.filter(Boolean);
if (parts[0]) {
// checks if scoped packaged
if (parts[0].startsWith("@")) {
const nameVersion = parts[1].split("@");
return {
name: `${parts[0]}/${nameVersion[0]}` || null,
version: nameVersion[1] || null,
path: parts.join("/") || null,
file:
(parts.length > 2 && parts.slice(parts.length - 1)[0]) ||
null,
directory: parts.slice(2, parts.length - 1).join("/") || null
};
} else {
const nameVersion = parts[0].split("@");
return {
name: nameVersion[0] || null,
version: nameVersion[1] || null,
path: parts.join("/") || null,
file:
(parts.length > 1 && parts.slice(parts.length - 1)[0]) ||
null,
directory: parts.slice(1, parts.length - 1).join("/") || null
};
}
} else {
return {
name: null,
version: null,
path: null,
file: null,
directory: null
};
}
};
export { parseUrl };
So how do we go from this to an importable script?
❌ Use a bundler but NO BUILD!.
❌ Use an ESM polyfill (kinda boring though and I don't want to research the smallest one).
🤦♀️ Use eval and strip off export
and function
declarations.
The final code looks like this:
const getParseUrl = () =>
fetch("/utils/parseUrl.js")
.then(x => x.text())
.then(x =>
x.replace(/\s*export {[^}]+\};/g, "").replace(/^const\s[^=]+=/, "")
);
Then we call it as such:
const { name, version } = eval(await getParseUrl())(url);
It's hacky but it sorta works.
So now maintenance is easier because if we update parseUrl
function it will get updated in the dependencyFetch
webworker. ✅ Provided we don't refactor the structure of parseUrl
but that's a problem for future Kara. 👍