Skip to content

Latest commit

Β 

History

History
310 lines (243 loc) Β· 13.4 KB

File metadata and controls

310 lines (243 loc) Β· 13.4 KB

SandboxJS - ECMAScript Feature Status

codecov

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


πŸ› Known Bugs & Limitations

The following limitations have been identified during testing:

  1. Computed property names - Object/class computed property names are not parsed correctly
  2. Unicode identifier escapes - \uXXXX escape sequences in variable names are not supported
  3. Labeled statements - Labels for break/continue are parsed but not properly implemented

βœ… Supported Features

SandboxJS supports the following ECMAScript features with comprehensive test coverage:

Arithmetic Operators

  • βœ… 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 Operators

  • βœ… 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

Comparison Operators

  • βœ… 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 Operators

  • βœ… 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

Assignment Operators

  • βœ… 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

Other Operators

  • βœ… 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'

Data Types

  • βœ… 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

Objects & Arrays

  • βœ… 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

Functions

  • βœ… 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} with new
  • βœ… Recursive functions - Linked list reverse example

Control Flow

Conditionals

  • βœ… 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

Loops

  • βœ… 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

  • βœ… 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

Error Handling

  • βœ… 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

Other

  • βœ… 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

Variables

  • βœ… 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/Await

  • βœ… async functions - (async () => 1)() β†’ Promise resolves to 1
  • βœ… 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

Other Built-in Objects

  • βœ… WeakMap - All methods work: set(), get(), has(), delete() (6 tests)
  • βœ… WeakSet - All methods work: add(), has(), delete()

Comments

  • βœ… Single-line comments - 1 // 2 β†’ 1
  • βœ… Multi-line comments - /* 2 */ 1 β†’ 1

Operator Precedence

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

❌ Not Supported Features


❌ Not Supported Features

The following ECMAScript features are not currently supported in SandboxJS:

HIGH PRIORITY

Classes (ES6)

  • ❌ class declarations
  • ❌ extends keyword (inheritance)
  • ❌ super keyword
  • ❌ Static methods
  • ❌ Class fields (public)
  • ❌ Private fields (#field)
  • ❌ Private methods
  • ❌ Static class fields
  • ❌ Static initialization blocks

Functions

  • ❌ Parameter default values - function fn(a = 1) { return a; }

Destructuring

  • ❌ 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

Generators (ES6)

  • ❌ Generator functions (function)* - function* gen() { yield 1; }
  • ❌ yield keyword
  • ❌ yield delegation*

Object Features

  • ❌ Getters in object literals - {get prop() { return 1; }}
  • ❌ Setters in object literals - {set prop(v) { this.val = v; }}

MEDIUM PRIORITY

Async Features

  • ❌ for-await-of loops - for await (const item of asyncIterable) { }
  • ❌ Async generators - async function* gen() { yield await Promise.resolve(1); }

LOW PRIORITY

Modules

Module features are not supported by design as SandboxJS is intended for sandboxed code execution:

  • ❌ import statements
  • ❌ export statements
  • ❌ Dynamic import()
  • ❌ import.meta

Other Advanced Features

  • ❌ Trailing commas in function parameters - function fn(a, b,) { }
  • ❌ Async iteration protocols - Symbol.asyncIterator

πŸ”’ Security-Related Restrictions (Intentionally Blocked)

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
  • πŸ”’ with statement
  • πŸ”’ arguments object (security risk, use rest parameters ...args instead)
  • πŸ”’ Execution beyond quota limits

πŸ“ Notes

  • 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