@@ -1086,6 +1086,8 @@ export class Program extends DiagnosticEmitter {
10861086 i64_new ( options . hasFeature ( Feature . ExtendedConst ) ? 1 : 0 , 0 ) ) ;
10871087 this . registerConstantInteger ( CommonNames . ASC_FEATURE_STRINGREF , Type . bool ,
10881088 i64_new ( options . hasFeature ( Feature . Stringref ) ? 1 : 0 , 0 ) ) ;
1089+ this . registerConstantInteger ( CommonNames . ASC_FEATURE_CLOSURES , Type . bool ,
1090+ i64_new ( options . hasFeature ( Feature . Closures ) ? 1 : 0 , 0 ) ) ;
10891091
10901092 // remember deferred elements
10911093 let queuedImports = new Array < QueuedImport > ( ) ;
@@ -3628,6 +3630,15 @@ export class Local extends VariableLikeElement {
36283630 /** Original name of the (temporary) local. */
36293631 private originalName : string ;
36303632
3633+ /** Whether this local is captured by a closure. */
3634+ isCaptured : bool = false ;
3635+
3636+ /** Environment slot index if captured, -1 otherwise. */
3637+ envSlotIndex : i32 = - 1 ;
3638+
3639+ /** The function whose environment this local is stored in. Set when captured. */
3640+ envOwner : Function | null = null ;
3641+
36313642 /** Constructs a new local variable. */
36323643 constructor (
36333644 /** Simple name. */
@@ -3785,6 +3796,32 @@ export class Function extends TypedElement {
37853796 /** Counting id of anonymous inner functions. */
37863797 nextAnonymousId : i32 = 0 ;
37873798
3799+ // Closure support
3800+
3801+ /** Set of locals from outer scopes that this function captures. Maps Local to slot index. */
3802+ capturedLocals : Map < Local , i32 > | null = null ;
3803+
3804+ /** The environment class for this function's captured locals, if any. */
3805+ envClass : Class | null = null ;
3806+
3807+ /** The local variable holding the environment pointer in outer function. */
3808+ envLocal : Local | null = null ;
3809+
3810+ /** The outer function whose environment this closure accesses. */
3811+ outerFunction : Function | null = null ;
3812+
3813+ /** Local variable in a closure function that caches the environment pointer from the global.
3814+ * This is needed because indirect calls can overwrite the global. */
3815+ closureEnvLocal : Local | null = null ;
3816+
3817+ /** Pre-scanned names of captured variables (set before compilation, used to mark locals). */
3818+ preCapturedNames : Set < string > | null = null ;
3819+
3820+ /** Whether this function requires an environment (is a closure). */
3821+ get needsEnvironment ( ) : bool {
3822+ return this . capturedLocals != null && this . capturedLocals . size > 0 ;
3823+ }
3824+
37883825 /** Constructs a new concrete function. */
37893826 constructor (
37903827 /** Name incl. type parameters, i.e. `foo<i32>`. */
0 commit comments