0

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.

Siavoshkc
  • 346
  • 2
  • 16

1 Answers1

0

Well after some research I think it works kinda like this: Suppose we are implementing zone.js. We implement the module like this:

function Zone(name, parent) {
this.name = name; this.parent = parent; this.localStorage = {},
    this.fork = function (name) { return new Zone(name, this) },
    this.run = function (f, fthis, args) {
        var formerZone = currentZone
        currentZone = this
        f.apply(fthis, args) 
        currentZone = formerZone
    }
}
//On initialization
var currentZone = new Zone("root", null)
module.exports.currentZone = function(){return currentZone}

And we use it like this:

const zone = require('./z.js')

//root zone
console.log(zone.currentZone())

//We create new zones that carry a reference to their parent
var zone2 = zone.currentZone().fork("newZone")

//We can run any function in a newly forked zone
zone2.run(() => {
    zone.currentZone().localStorage.ctx = "custom context/zone related data"
    console.log(zone.currentZone())
    //Zone will not change back until we return from here so any nested call
    //will still be in this zone
})

//Back to parent zone (root)
console.log(zone.currentZone())

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.

Siavoshkc
  • 346
  • 2
  • 16