From e233befe10ebcf9971680a30cc4d6c90ee24631f Mon Sep 17 00:00:00 2001 From: adamscybot Date: Sat, 8 Jun 2024 19:30:48 +0100 Subject: [PATCH] Add undocumented API to hook into when a new frame is created. This is helpful in scenarios where you wish to debug the environment behavior, or modify the env for advanced scenarios. As the callback is set via a Symbol, it can not be manipulated or read inside a query. See jsonata-js/jsonata/#700. --- src/jsonata.js | 12 +++++++++++- test/implementation-tests.js | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/jsonata.js b/src/jsonata.js index b7dfad53..aa3c36b5 100644 --- a/src/jsonata.js +++ b/src/jsonata.js @@ -1837,7 +1837,7 @@ var jsonata = (function() { */ function createFrame(enclosingEnvironment) { var bindings = {}; - return { + const newFrame = { bind: function (name, value) { bindings[name] = value; }, @@ -1857,6 +1857,16 @@ var jsonata = (function() { ancestry: [ null ] } }; + + if (enclosingEnvironment) { + var framePushCallback = enclosingEnvironment.lookup(Symbol.for('jsonata.__createFrame_push')); + if(framePushCallback) { + framePushCallback(enclosingEnvironment, newFrame); + } + } + + + return newFrame } // Function registration diff --git a/test/implementation-tests.js b/test/implementation-tests.js index 6df7e679..c7cb2f09 100644 --- a/test/implementation-tests.js +++ b/test/implementation-tests.js @@ -1024,6 +1024,21 @@ describe("Tests that include infinite recursion", () => { }); }); +describe("Tests that use internal frame push callbacks", () => { + describe("frame push callback bound to expression", function() { + it("calls callback when new frame created", function(done) { + var expr = jsonata("( )"); + expr.assign(Symbol.for('jsonata.__createFrame_push'), function(parentEnv, newEnv) { + expect(parentEnv).to.not.equal(newEnv); + expect(parentEnv).to.include.keys(['lookup', 'bind']); + expect(newEnv).to.include.keys(['lookup', 'bind']); + done(); + }); + expr.evaluate(); + }); + }); +}); + /** * Protect the process/browser from a runnaway expression * i.e. Infinite loop (tail recursion), or excessive stack growth