From 93aaaa43a11235dc9aac6d552c91d63541d71572 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Fri, 20 Feb 2026 22:02:26 -0600 Subject: [PATCH] lexical this --- mcode.cm | 8 ++++++++ tests/suite.cm | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/mcode.cm b/mcode.cm index e5cbb58f..d993acd1 100644 --- a/mcode.cm +++ b/mcode.cm @@ -2767,6 +2767,7 @@ var mcode = function(ast) { var result = null var saved_label = 0 var saved_func = 0 + var captured_this = 0 push(parent_states, saved) @@ -2818,6 +2819,13 @@ var mcode = function(ast) { s_max_slot = s_next_temp_slot } + // Arrow functions capture the enclosing this via closure + if (is_arrow) { + captured_this = alloc_slot() + emit_3("get", captured_this, saved.this_slot, 1) + s_this_slot = captured_this + } + // Default parameter initialization ps = 1 _i = 0 diff --git a/tests/suite.cm b/tests/suite.cm index 0eb68b82..7e975153 100644 --- a/tests/suite.cm +++ b/tests/suite.cm @@ -3498,4 +3498,59 @@ return { } }, + // ============================================================================ + // ARROW FUNCTION LEXICAL THIS + // ============================================================================ + + test_arrow_captures_this: function() { + var obj = { + value: 42, + getIt: function() { + var arrow = () => this.value + return arrow() + } + } + if (obj.getIt() != 42) return "arrow should capture enclosing this" + }, + + test_arrow_captures_this_nested: function() { + var obj = { + value: 99, + getIt: function() { + var outer = () => { + var inner = () => this.value + return inner() + } + return outer() + } + } + if (obj.getIt() != 99) return "nested arrows should capture enclosing this" + }, + + test_arrow_this_not_rebound_by_method_call: function() { + var obj = { + value: 10, + getIt: function() { + var arrow = () => this.value + return arrow() + } + } + var other = { value: 20, stolen: obj.getIt } + if (other.stolen() != 20) return "setup failed" + if (obj.getIt() != 10) return "arrow this should come from enclosing method" + }, + + test_arrow_this_with_regular_function_this: function() { + var obj = { + value: 7, + getIt: function() { + var arrow = () => this.value + var regular = function() { return this } + if (regular() != null) return "regular fn direct call should have null this" + return arrow() + } + } + if (obj.getIt() != 7) return "arrow should capture this while regular fn does not" + }, + }