we (web engine): Experimental web browser project to understand the limits of Claude

JS Functions, closures, and var/let/const scoping #266

Open pierrelf.com
targeting main
Open opened by and assigned to pierrelf.com
targeting main

Implements issue 3mhn3mfmffa2k

Changes #

Adds upvalue-based closure system using GC-allocated cells, enabling JavaScript functions to capture and mutate variables from enclosing scopes.

Bytecode (bytecode.rs) #

  • New opcodes: NewCell, CellLoad, CellStore, LoadUpvalue, StoreUpvalue
  • UpvalueDef struct describing how closures capture parent variables
  • upvalue_defs field on Function for capture metadata

VM (vm.rs) #

  • HeapObject::Cell(Value) variant for mutable captured variable storage
  • FunctionData.upvalues and CallFrame.upvalues for runtime closure state
  • CreateClosure resolves upvalue_defs from parent scope registers/upvalues
  • GC tracing updated for cells and function upvalues

Compiler (compiler.rs) #

  • Free variable analysis: collect_free_vars with transitive capture support
  • Pre-scan inner function bodies to identify captured variables
  • Captured locals compiled as cells (NewCell + CellLoad/CellStore)
  • Inner functions use LoadUpvalue/StoreUpvalue for captured variables
  • const declarations enforce immutability at compile time
  • Method calls (obj.method()) set this before invocation

Tests #

  • 11 new tests covering: basic closures, returned closures, mutation, shared variables, arrow captures, nested/transitive captures, parameter capture, const immutability, and method-call this binding
  • All 256 existing tests continue to pass

This pull request has no versions submitted yet.