@@ -677,6 +677,30 @@ pub const Environment = struct {
677677 return null;
678678 }
679679
680+ /// Look up a binding known to live in this exact declarative environment.
681+ /// Mapped-arguments parameter aliases use this: a parameter map never targets
682+ /// an outer scope or module alias, so the full parent-chain/alias walk only
683+ /// adds lock/hash churn on hot no-GIL readers.
684+ pub fn getLocal(self: *Environment, name: []const u8) ?Value {
685+ self.lockBindings();
686+ defer self.unlockBindings();
687+ return self.vars.get(name);
688+ }
689+
690+ /// Assign a binding known to live in this exact declarative environment.
691+ /// Returns false if the binding is absent; callers that need sloppy global
692+ /// creation should use `assign` instead.
693+ pub fn assignLocal(self: *Environment, name: []const u8, v: Value) bool {
694+ self.lockBindings();
695+ defer self.unlockBindings();
696+ if (self.vars.getPtr(name)) |ptr| {
697+ gc_mod.barrierValueFrom(self, v);
698+ ptr.* = v;
699+ return true;
700+ }
701+ return false;
702+ }
703+
680704 pub fn bindingAllocator(self: *const Environment) std.mem.Allocator {
681705 return self.bindings_allocator orelse self.arena;
682706 }
@@ -39046,14 +39070,14 @@ pub fn argMapSever(o: *value.Object, i: usize) void {
3904639070pub fn argMapGet(o: *value.Object, i: usize) ?Value {
3904739071 const nm = argMapName(o, i) orelse return null;
3904839072 const env: *Environment = @ptrCast(@alignCast(o.arg_map_env.?));
39049- return env.get (nm);
39073+ return env.getLocal (nm);
3905039074}
3905139075
3905239076/// Write a mapped index's parameter binding.
3905339077pub fn argMapSet(o: *value.Object, i: usize, v: Value) void {
3905439078 const nm = argMapName(o, i) orelse return;
3905539079 const env: *Environment = @ptrCast(@alignCast(o.arg_map_env.?));
39056- env.assign (nm, v) catch {} ;
39080+ _ = env.assignLocal (nm, v);
3905739081}
3905839082
3905939083/// CanonicalNumericIndexString(key): the Number a key denotes when it is the
0 commit comments