4 ms·
Let me sketch out my own interpretation of the problem. JavaScript programs lack declarative structure. There is no way to declare a class with a fixed set of
by mraleph 14y ago
Let me sketch out my own interpretation of the problem.
JavaScript programs lack declarative structure.
There is no way to declare a class with a fixed set of fields and methods. Instead JavaScript program creates functions and sets up their prototype property as it executes.
No way to declare a module. Instead developers create and immediately invoke a nameless closure.
One can say that the structure (things that people view as "classes" and "modules") behind JavaScript program is the side-effect of this very program executing. There is no clear border between "structure initialization" and execution.
So the first issue arises: to snapshot something you need to guarantee that deserialized snapshot will result in the very same "structure" that would arise from executing this code from scratch. This imposes certain restrictions on the way the JavaScript code should be written and how its initialization should be laid out. If for example application starts interacting with DOM early in its "initialization" phase then this is hard to snapshot correctly.
But an opposite is true as well: other programs (scripts) executing in the same environment might affect the structure that JavaScript program weavers as it runs.
Consider for example the following code:
function Point() {
}
Point.prototype.distance = function () { /* ... */ };
It might look like we could snapshot it and then unconditionally deserialize it into a Point function with a distance property on an object in its prototype property. But this is not true. If our deserialization does not happen in the clean environment (e.g. we are not the very first thing that is running on the page) then somebody can install "distance" property with a setter on the Object.prototype thus altering execution of our initialization entirely. This means that deserialization code must account for that.
So we have two points to care about:
(a) JS code must be written in a special way to benefit from snapshotting, serializer must bail out from the attempt to snapshot "unsound" initialization code;
(b) deserializer must ensure correctness when unpacking.
If you ensure that both hold then you can actually snapshot your JS code and benefit from it.
V8 in fact does this internally: some JavaScript builtins are written in JavaScript and "snapshotted" to speed up their initialization. But V8 snapshots are cutting corners:
- Point (a) is ensured manually. "Unsound" initialization code in builtins just leads to mysterious bugs. There is no verification, toolchain does not reject any code.
- Point (b) is guaranteed because deserializer is applied when the world is empty and untouched by the user code.
This is not something you can use for an arbitrary JS code AS IS... and filling up the gaps requires hard efforts on both VM and application side.
Dart does not have any problems like that because the structure behind the program is static. So snapshotting is simple to implement and it works for any application, not requiring any "restructuring" from the app developer.