Skip to content

milahu/awesome-javascript-interpreters

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 

Repository files navigation

awesome-javascript-interpreters

javascript interpreters

repo stars last commit comments
bellard/quickjs GitHub Repo stars GitHub last commit WASM, benchmarks
patriksimek/vm2 GitHub Repo stars GitHub last commit nodejs
NeilFraser/JS-Interpreter GitHub Repo stars GitHub last commit based on vm-browserify, old, no package
sablejs/sablejs GitHub Repo stars GitHub last commit benchmarks, ES5.1 = ES2009
engine262/engine262 GitHub Repo stars GitHub last commit ES2020, complex interface, stepped execution, empty sandbox
bplok20010/eval5 GitHub Repo stars GitHub last commit ES5 = ES2009
Siubaak/sval GitHub Repo stars GitHub last commit ES2019, simple interface
metaes/metaes GitHub Repo stars GitHub last commit

old projects

last commit is over 1 year ago

repo stars last commit comments
bramblex/jsjs GitHub Repo stars GitHub last commit
jterrace/js.js GitHub Repo stars GitHub last commit based on SpiderMonkey, last version 2012
mozilla/narcissus GitHub Repo stars GitHub last commit archived
zuluoaaa/makeJs GitHub Repo stars GitHub last commit
jrainlau/canjs GitHub Repo stars GitHub last commit
hacksparrow/safe-eval GitHub Repo stars GitHub last commit nodejs
browserify/vm-browserify GitHub Repo stars GitHub last commit substack/vm-browserify
jkeylu/evil-eval GitHub Repo stars GitHub last commit

selection criteria

  • browser or nodejs: does it run in a browser (web APIs)?
  • error handling: message, location, stack
  • simple interface or complex interface
  • how empty is the default sandbox? for example, does console.log work?
  • simple interface between sandbox and environment: import, export, call, return, throw
  • async code: does the interpreter block the main thread?
  • stepped execution is supported? needed for debugging
  • ecmascript version: what spec is implemented?
  • spec compliance: how complete is the implementation?
  • compatibility: can it run unmodified code?
  • createFunction - does it have a replacement for const f = new Function("x", "y", "return x + y")?
  • createModule - does it have a replacement for const m = await import("data:text/javascript,export function f(x, y) { return x + y; }")?
  • performance: how much slower than native speed? is performance relevant for this use case?
  • WASM or javascript? WASM is faster, but more complex

ECMAScript version

some test code

console.log("ES2009", Array.isArray([1, 2]))
console.log("ES2015", [1, 2].find(x => x == 1))
console.log("ES2016", [1, 2].includes(1))
console.log("ES2017", Object.entries({a: 1}))
console.log("ES2018", [ ...[1, 2] ])
console.log("ES2019", Object.fromEntries([["a",1]]))
console.log("ES2020", null ?? "asdf")

use cases

when do we need a javascript interpreter?

inject script

workaround for

globalThis.callback = (value) => console.log(value == 3)
const source = `
  const x = 1
  const y = 2
  globalThis.callback(x + y)
`
const script = document.createElement("script")
script.textContent = source
document.body.append(script)

which can break with CSP

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'".

eval code

workaround for

const x = 1
const y = 2
const v = eval("x + y")
console.log(v == 3)

which can break with CSP

EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self'".

compile functions

workaround for

const f = new Function("x", "y", "return x + y")
console.log(f(1, 2) == 3)
console.log(f(3, 4) == 7)

which can break with CSP

EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self'".

compile modules

workaround for

(async () => {
const m = await import("data:text/javascript,export function f(x, y) { return x + y; }")
console.log(m.f(1, 2) == 3)
console.log(m.f(3, 4) == 7)
})()

which can break with CSP

Refused to load the script ... because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

not needed

a javascript interpreter is not needed is some cases

web extensions

https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#loading_content_scripts

Loading content scripts

You can load a content script into a web page in one of three ways:

1. At install time, into pages that match URL patterns.

Using the content_scripts key in your manifest.json, you can ask the browser to load a content script whenever the browser loads a page whose URL matches a given pattern.

2. At runtime, into pages that match URL patterns.

Using the contentScripts API, you can ask the browser to load a content script whenever the browser loads a page whose URL matches a given pattern. (This is similar to method 1, except that you can add and remove content scripts at runtime.)

3. At runtime, into specific tabs.

In Manifest V2, using tabs.executeScript(), or Manifest V3, using scripting.executeScript(), you can load a content script into a specific tab whenever you want. (For example, in response to the user clicking on a browser action.)

There is only one global scope per frame, per extension. This means that variables from one content script can directly be accessed by another content script, regardless of how the content script was loaded.

Using methods (1) and (2), you can only load scripts into pages whose URLs can be represented using a match pattern.

Using method (3), you can also load scripts into pages packaged with your extension, but you can't load scripts into privileged browser pages (like "about:debugging" or "about:addons").

https://github.com/violentmonkey/violentmonkey/blob/master/src/background/utils/preinject.js

const contentScriptsAPI = browser.contentScripts;

// ...

function registerScriptDataFF(inject, url) {
  for (const scr of inject[ENV_SCRIPTS]) {
    scr.code = scr[__CODE];
  }
  return contentScriptsAPI.register({
    js: [{
      code: `${resolveDataCodeStr}(${JSON.stringify(inject)})`,
    }],
    matches: url.split('#', 1),
    runAt: 'document_start',
  });
}

see also

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published