whatwg / loader

Loader Standard
https://whatwg.github.io/loader/
Creative Commons Zero v1.0 Universal
607 stars 45 forks source link

PreEvaluate/PostEvaluate stages #142

Closed ghost closed 8 years ago

ghost commented 8 years ago

Following the discussion engaged about an Execute Hook #47, I would see value in the ability for developers to hook into the PreEvaluate & PostEvaluate stages of modules loading.

The PreEvaluate stage contains the state of the runtime prior to module evaluation, and the PostEvaluate stage contains the state of the runtime after module evaluation.

The access to those stages may allow for various scenarios both in development and in production, like runtime diffing and analysis, orchestration and advanced tracing strategies, modules based state-machines, etc, that would not be possible within the instantiation stage only.

Update: renaming to PreEvaluate and PostEvaluate for conformity with the spec.

ghost commented 8 years ago

Similarly, and echoing the issue #18 about hooks and state, and the issue #89 about manually canceling pipelines stages, I would find quite useful to have, instead of single points entries into the loader pipeline, dual point entries referring to the beginning and the ending of each stage:

preFetch/postFetch
preTranslate/postTranslate
preInstantiate/postInstantiate
preEvaluate/postEvaluate

Does it make any sense ?

caridy commented 8 years ago

you can achieve this by simply defining a hook that applies AOP for the existing (or default) hook, and return a promise that allow you to run an async process before and after.

ghost commented 8 years ago

hmm, that would work if there was an evaluate hook, but there is no way apparently that an import statement informs its context when it has been evaluated.

One could do it with Loader.import returning a promise but coding everything like this would result in lots of spaghetti code, and won't take into account the declarative "import" statements:

Loader.import(module).then(function(module){
//postEvaluate Stage
}).then(Loader.import(othermodule).then(function(othermodule){
//postEvaluate Stage
}));

Whereas:

import exp from 'module';
import otherexp from 'othermodule';

and

function evaluate(){
//PreEvaluate Stage

//evaluate

//PostEvaluate Stage
}

would be simpler...

caridy commented 8 years ago

no, that's not what I meant, and importing a module does not imply evaluation. but before I try to explain how to achieve this, I wonder is you have more use-cases, specifically things that you might do in production?

it seems that all the use cases that you mentoned are related to instrumentation, which is very low-level feature, and having a hard time to achieve is probably not an issue. I think the realms and the instantitate hook will be enough here.

ghost commented 8 years ago

perhaps it is, and am going beyond the functionality of the loader.

besides instrumentation, debugging or more advanced introspective usage of the loader functionality (because of its intrinsic knowledge of modules), I was thinking, as one use-case, modules like sandboxed processes in an Actor Model context, with the Loader acting as a global registry of processes.

Once we import the modules, they have to communicate with each other, and the Loader seems to be a good center of communication between the modules, as it holds all the information about each and every module loaded at runtime, in his registry.

Once we know when a module is evaluated, and therefore that it is an active actor of the application, that it is loaded, we can make it to participate to the communication pipeline between modules, and therefore messages can be sent to and from it.

This would require getting the information for when a module is ready, like the onload event of a script tag, as I conveive a postEvaluate hook somehow as a ready stage.

If the ready stage does not have a hook, would the modules be evented, with a ready event to listen to, like an onload event ?

caridy commented 8 years ago

Ok, that confirms my suspicious! you will probably create a realm, and evaluate any model-type module in that realm, maybe using a proxy as the global of the realm to have full control of what each module is attempting to do.

I am not trying to judge your architecture, just to make sure that what we have is flexible enough to support it. But I must say that if what you need is a communicacion layer between similar modules, you could probably do the same using a module that they are required to import to access this communicacion api.

ghost commented 8 years ago

I see, I'll have to get more information about the realm. Thanks for having taken the time to answer and for the suggestions. Have to ponder more about all this anyway. Closing the issue for now, as it is not a main one. A

caridy commented 8 years ago

all questions are welcome! it helps us to validate what we have here.