Aran is a npm module for instrumenting JavaScript code. Aran was designed as a generic infrastructure for building various development-time dynamic program analyses such as: object and function profiling, debugging, control-flow tracing, taint analysis, and concolic testing. Aran is a JavaScript library without any dependencies that only exports functions for manipulating estree. Hence, additional work is required to deploy program analysis onto projects.
Disclaimer: Aran started as an academic research project and is used at SOFT lab to support publications and run experiments. Aran provides extensive support for ECMAScript2024 and achieves a 99.7% success rate against test262. However, it has rarely been used to instrument large-scale programs and performance overhead may cause issues when analyzing time-sensitive programs.
Aran can be installed with npm install aran
. Since Aran exclusively
manipulates estree, it requires both a
parser and a code generator to function. We recommend using
acorn as the parser and
astring as the code generator. Below is
a minimal working example demonstrating the use of acorn.parse
,
aran.instrument
, and astring.generate
:
npm install aran acorn astring
import { generate } from "astring";
import { parse } from "acorn";
import { instrument } from "aran";
globalThis._ARAN_ADVICE_ = {
"apply@around": (_state, callee, this_arg, args, location) => {
console.dir({ callee, this_arg, args, location });
return Reflect.apply(callee, this_arg, args);
},
};
globalThis.eval(
generate(
instrument(
{
kind: "eval",
path: "main",
root: parse("console.log('Hello!');", { ecmaVersion: 2024 }),
},
{
mode: "standalone",
advice_global_variable: "_ARAN_ADVICE_",
pointcut: ["apply@around"],
},
),
),
);
{
callee: [Function: readGlobalVariable],
this_arg: undefined,
args: [ 'console' ],
location: 'main#$.body.0.expression.callee.object'
}
{
callee: [Function: getValueProperty],
this_arg: undefined,
args: [
Object [console],
'log'
],
location: 'main#$.body.0.expression.callee'
}
{
callee: [Function: log],
this_arg: Object [console],
args: [ 'Hello!' ],
location: 'main#$.body.0.expression'
}
Hello!
Aran simplifies the instrumentation of JavaScript code by transpiling it into a minimal variant called AranLang. Instrumentation is performed on AranLang before transpiling it back to JavaScript. Aran provides the following functions:
setupile
: Generates a setup program (JavaScript) that should be evaluated before any AranLang program. This requirement can be removed by settingconf.mode
ofretropile
to"standalone"
instead of"normal"
. The standalone mode works only with single-source programs.transpile
: Transpile an JavaScript program to AranLang.weaveStandard
: Weave a standard aspect into an AranLang program.weaveFlexible
: Weave a flexible aspect into an AranLang program.retropile
: Transpile an AranLang program back to JavaScript.instrument
: Instrument a JavaScript program by chaining:transpile
,weaveStandard
, andretropile
.
Beside performance overhead, Aran has some known issues that may cause instrumented programs to no behave as their pre-instrumented version.
- Corrupt error stack
- Corrupt function string representation
- Duplicate super prototype access
- Early module declaration
- Early script declaration
- Internal deep eval declaration
- Missing iterable return call in pattern
- No arguments two-way binding
- No dynamic function property
- Path membrane break local eval
- Weave membrane miss deep eval
- Wrong realm for default prototype
- Wrong this parameter in with in eval
Most of these issues requires fairly convoluted code to arise. In practice, the issue that is most susceptible to cause a program to behave differentially is early script declaration.
I'm Laurent Christophe a phd student at the Vrij Universiteit of Brussel. My promoters are Coen De Roover and Wolfgang De Meuter.