It has been boggling my mind for days and I couldn't figure it out. I was trying to create a simple example as follows:
- Define a function "run(f)" (in module "zone") which gets another function to run.
- An specific variable "ctx" be accessible in f like it is in global context.
- ctx be specific to each run of f.
Another scenario is to have f require a module "zone" and access its own specific ctx using an imported getter.
In the first scenario I don't know how to propagate a new ctx from run() into f() and it descendants. The closest I've got was using eval(f.toString()) in run() so it could capture something in run() and or zone.
In the second scenario I couldn't find a way so that zone getter knows which call stack is calling it.
Well after some research I think it works kinda like this: Suppose we are implementing zone.js. We implement the module like this:
And we use it like this:
Now we have an overview of what happens. But what if there are async calls? In that scenario JS VM may switch between zones before our .run() returns. Our module must track and trap any action that might change currentZone. One case is to patch Promises for example. Each time a Promise is created we place a trap code to catch the resolution/rejection of that promise. Our trap code switches currentZone to that Promise's zone whenever it is resolved/rejected. Zone.js patches various modules to track the zones.
This writing may not be accurate of course and may contain technical errors as there are some aspects of the matter which are not crystal clear in my head.