This document describes the current implementation status of ECMAScript features in SandboxJS.
Test Coverage: 1001 total tests | Code Coverage: ~96% statement coverage, ~90% branch coverage
The following limitations have been identified during testing:
- Computed property names - Object/class computed property names are not parsed correctly
- Unicode identifier escapes -
\uXXXXescape sequences in variable names are not supported - Labeled statements - Labels for break/continue are parsed but not properly implemented
SandboxJS supports the following ECMAScript features with comprehensive test coverage:
- β
Addition -
1+1β2 - β
Subtraction -
1 * 2 + 3 * (4 + 5) * 6β164 - β
Multiplication -
1 * 2β2 - β
Division -
1+2*4/5-6+7/8 % 9+10-11-12/13*14β-16.448... - β
Modulus -
test2 %= 1β0 - β
Exponentiation -
2 ** 3β8,3 ** 2 ** 2β81 - β
Exponentiation assignment -
test2 **= 0β1 - β
Unary plus -
+'1'β1 - β
Unary minus -
-'1'β-1
- β
Logical AND -
true && true || falseβtrue - β
Logical OR -
test2 || falseβ3 - β
Logical NOT -
!test2βfalse,!!test2βtrue - β
Nullish coalescing -
null ?? 'default'β'default',0 ?? 'default'β0
- β
Equality -
test2 == '3'βtrue - β
Strict equality -
test2 === '3'βfalse - β
Inequality -
test2 != '3'βfalse - β
Strict inequality -
test2 !== '3'βtrue - β
Less than -
test2 < 3βfalse - β
Greater than -
test2 > 3βfalse - β
Less than or equal -
test2 <= 3βtrue - β
Greater than or equal -
test2 >= 3βtrue
- β
Bitwise AND -
test2 & 1β1 - β
Bitwise OR -
test2 | 4β7 - β
Bitwise NOT -
~test2β-2 - β
Bitwise XOR -
test2 ^= 1β1 - β Left shift - Tested in complex expressions
- β Right shift - Tested in complex expressions
- β Unsigned right shift - Tested in complex expressions
- β
Left shift assignment -
let x = 5; x <<= 1β10 - β
Right shift assignment -
let x = 8; x >>= 1β4 - β
Unsigned right shift assignment -
let x = 8; x >>>= 2β2 - β
XOR assignment -
test2 ^= 1β1 - β
AND assignment -
test2 &= 3β1 - β
OR assignment -
test2 |= 2β3
- β
Simple assignment -
test2 = 1β1 - β
Addition assignment -
test2 += 1β2 - β
Subtraction assignment -
test2 -= 1β1 - β
Multiplication assignment -
test2 *= 2β2 - β
Division assignment -
test2 /= 2β1 - β
Exponentiation assignment -
test2 **= 0β1 - β
Modulus assignment -
test2 %= 1β0 - β
XOR assignment -
test2 ^= 1β1 - β
AND assignment -
test2 &= 3β1 - β
OR assignment -
test2 |= 2β3 - β
Logical AND assignment (&&=) -
let x = 10; x &&= 5β5 - β
Logical OR assignment (||=) -
let x = 0; x ||= 5β5 - β
Nullish coalescing assignment (??=) -
let x = null; x ??= 5β5 - β
Post-increment -
test2++β1 - β
Pre-increment -
++test2β3
- β
Conditional (ternary) -
test[test2] ? true : false ? 'not ok' : 'ok'β'ok' - β
Optional chaining -
!({}).a?.aβtrue,({}).a?.toString()βundefined - β
Comma operator -
1,2β2 - β
typeof -
typeof '1'β'string',typeof x === 'undefined'βtrue - β
instanceof -
{} instanceof Objectβtrue - β
in operator -
'a' in {a: 1}βtrue - β
delete operator -
delete 1βtrue,let a = {b: 1}; return delete a.bβtrue - β
void operator -
void 2 == '2'βfalse - β
new operator -
new Date(0).toISOString()β'1970-01-01T00:00:00.000Z'
- β
Numbers -
2.2204460492503130808472633361816E-16β Scientific notation - β
BigInt -
(1n + 0x1n).toString()β'2' - β
Binary literals -
0b1010β10,0B1111β15,0b1010nβ'10'(BigInt),0b1_000β8(with separators) - β
Octal literals -
0o17β15,0O77β63,0o17nβ'15'(BigInt),0o7_777β4095(with separators) - β
Strings -
"test2"β'test2' - β
Template literals -
`test2 is ${`also ${test2}`}`β'test2 is also 1' - β
Tagged template functions -
tag`hello ${"world"}`β function receives string parts and interpolated values - β
Escape sequences -
"\\"β'\\',"\\xd9"β'Γ',"\\n"β'\n' - β
Boolean -
true,false - β
null -
null ?? 'default'β'default' - β
undefined -
typeof x === 'undefined'βtrue - β
Arrays -
[test2, 2]β[1, 2] - β
Objects -
{"aa": test[0](), b: test2 * 3}β{ "aa": 1, "b": 3 } - β
Regular expressions -
/a/.test('a')βtrue,/a/i.test('A')βtrue
- β
Object literals -
{a: 1, b: 2}β{ a: 1, b: 2 } - β
Array literals -
[1, 2]β[1, 2] - β
Property access (dot) -
a.b.cβ2 - β
Property access (bracket) -
a['b']['c']β2 - β
Computed property names -
{"aa": test[0]()}β{ "aa": 1 } - β
Object spread -
{a: 1, ...{b: 2, c: {d: test2,}}, e: 5}β Full object - β
Array spread -
[1, ...[2, [test2, 4]], 5]β[1, 2, [3, 4], 5] - β
Object method shorthand -
let y = {a: 1, b(x) {return this.a + x}}; return y.b(2)β3
- β
Function declarations -
function f(a) { return a + 1 } return f(2);β3 - β
Function expressions -
(function () { return 1 })()β1 - β
Arrow functions (single param) -
(a => a + 1)(1)β2 - β
Arrow functions (multiple params) -
((a) => {return a + 1})(1)β2 - β
Arrow functions (expression body) -
(a => a + 1)(1)β2 - β
Arrow functions (block body) -
(() => {return 1})()β1 - β
Async arrow functions -
(async () => 1)()β1 - β
Async function expressions -
(async () => await 1)()β1 - β
Rest parameters -
[0,1].filter((...args) => args[1])β[1] - β
Spread in function calls -
Math.pow(...[2, 2])β4 - β
Constructor functions -
function LinkedListNode(e){this.value=e,this.next=null}withnew - β Recursive functions - Linked list reverse example
- β
if statement -
if (true) { return true; } else return falseβtrue - β
else statement -
if (false) { return true; } else return falseβfalse - β
if/else chains -
if (false) return true; else if (false) {return true} else return falseβfalse - β Nested if statements - Complex nested if/else with 9 levels
- β
Inline ternary -
true ? 1 : 2β1
- β
for loop -
let x; for(let i = 0; i < 2; i++){ x = i }; return x;β1 - β
while loop -
let x = 2; while(--x){ }; return x;β0 - β
do-while loop -
let x = 1; do {x++} while(x < 1); return x;β2 - β
for-of loop -
for(let i of [1,2]){ return i };β1 - β
for-in loop -
for(let i in [1,2]){ return i };β'0' - β
break statement -
for(let i = 0; i < 2; i++){ x = i; break; }β Exits early - β
continue statement -
for (let i = 0; i < 5; i++) { if (i === 2) continue; sum += i; }β Skips iteration
- β
switch statement -
switch(1) {case 1: b = 2; break; case 2: b = 3; default: b = 4}; return bβ2 - β case clauses - Multiple case tests
- β
default clause -
switch(3) {case 1: b = 2; break; case 2: b = 3; default: b = 4}; return bβ4 - β
Fall-through behavior -
switch(1) {case 1:b = 2; case 2: b = 3; default: b = 4}; return bβ4
- β
try/catch -
try {a.x.a} catch {return 1}; return 2β1 - β
try/catch with exception variable -
try { throw new Error('msg'); } catch(e) { return e.message; }β'msg' - β
finally block -
try { return 1; } finally { x = 2; }β Finally executes before return - β
finally overrides return -
try { return 1; } finally { return 2; }β2 - β
finally overrides error -
try { throw Error('a'); } finally { throw Error('b'); }β Error: 'b' - β
throw statement -
throw new Error('test')β Error with message
- β
Code blocks -
{let j = 1; i += j;}β Block scope - β
this binding -
let y = {a: 1, b(x) {return this.a + x}}β Method context - β
Closures -
const a = () => {return 1}; const b = () => {return 2}; return (() => a() + b())()β3
- β
var declaration -
var i = 1; return i + 1β2 - β
let declaration -
let j = 1; return j + 1β2 - β
const declaration -
const k = 1; return k + 1β2 - β
const immutability -
const l = 1; return l = 2β Error
- β
async functions -
(async () => 1)()β Promise resolves to1 - β
await keyword -
(async () => await 1)()β1 - β
await with promises -
(async () => await (async () => 1)())()β1 - β
async with variables -
let p = (async () => 1)(); return (async () => 'i = ' + await p)()β'i = 1' - β
Async arrow functions -
let i = 0; (async () => i += 1)(); return i;β1
- β
WeakMap - All methods work:
set(),get(),has(),delete()(6 tests) - β
WeakSet - All methods work:
add(),has(),delete()
- β
Single-line comments -
1 // 2β1 - β
Multi-line comments -
/* 2 */ 1β1
Comprehensive operator precedence testing has been implemented with 35 tests covering:
- NOT (!) with comparison operators
- Logical NOT with AND/OR
- Comparison operator chaining
- Bitwise vs logical operators
- Bitwise shift with arithmetic
- Mixed bitwise operators (correct precedence: shift > & > ^ > |)
- Exponentiation (right-associative)
- typeof, delete, void with various operators
- Optional chaining and nullish coalescing
- Increment/decrement with arithmetic
- Multiple unary operators
- Comma operator in expressions
The following ECMAScript features are not currently supported in SandboxJS:
- β class declarations
- β extends keyword (inheritance)
- β super keyword
- β Static methods
- β Class fields (public)
- β Private fields (#field)
- β Private methods
- β Static class fields
- β Static initialization blocks
- β Parameter default values -
function fn(a = 1) { return a; }
- β Array destructuring -
const [a, b] = [1, 2] - β Object destructuring -
const {a, b} = {a: 1, b: 2} - β Nested destructuring
- β Destructuring with defaults -
const {a = 1} = {} - β Destructuring in function parameters -
function fn({a, b}) { } - β Rest in destructuring -
const [a, ...rest] = [1, 2, 3] - β Computed property names in destructuring
- β Generator functions (function)* -
function* gen() { yield 1; } - β yield keyword
- β yield delegation*
- β Getters in object literals -
{get prop() { return 1; }} - β Setters in object literals -
{set prop(v) { this.val = v; }}
- β for-await-of loops -
for await (const item of asyncIterable) { } - β Async generators -
async function* gen() { yield await Promise.resolve(1); }
Module features are not supported by design as SandboxJS is intended for sandboxed code execution:
- β import statements
- β export statements
- β Dynamic import()
- β import.meta
- β Trailing commas in function parameters -
function fn(a, b,) { } - β Async iteration protocols -
Symbol.asyncIterator
These features are intentionally blocked for security reasons:
- π Direct access to global scope
- π Access to
__proto__(prototype pollution prevention) - π Global object pollution
- π Prototype method overriding
- π Access to non-whitelisted globals
- π Access to non-whitelisted prototype methods
- π
withstatement - π
argumentsobject (security risk, use rest parameters...argsinstead) - π Execution beyond quota limits
- Priority Levels:
- HIGH: Common patterns used frequently in production code
- MEDIUM: Less common but still important for completeness
- LOW: Edge cases and advanced features with limited use
- Implementation Focus: SandboxJS focuses on core ES5-ES2018 features with strong security controls
- Performance: Advanced meta-programming features are omitted to maintain sandbox safety