Here are the details. By a “prototype tree” I mean a structure that is a tree from the standpoint of the object-to-own-property-value relation, but in which prototype chains and functions may appear. Here is an example of such a structure:
Here is a formal definition.
Two operations can be defined which in combination make prototype trees suitable for use as components: instantiation and serialization. Together, these enable the assembly of applications from stored elements. The assemblies have a uniform structure which mates well to a user interface in which prototype structure is exposed. The idea has been worked out in detail for a particular use-case: diagrams. See https://protopedia.org.
The second operation is serialization. This is implemented by assigning numeric codes to the nodes of the object graph to be serialized, and then building a JSON-compatible description of the graph, including prototype chains. Here is some code.
In the diagramming application, the components are visual elements (arrows, boxes, labels, and the like), and assemblies thereof (i.e. diagrams and their parts). Prototype trees fit the diagramming application well, due to the repetitive use of common elements in diagrams, which is captured by repeated instantiation of common prototype trees. An unusually close integration of coding and UI work becomes possible, since parts retain their UI-adjustability when assembled by code.
The ProtoPedia code base is freely available under the MIT license.
Here is a sketch of how instantiation works:
Let T⁰ be the structure to be instantiated. First create a deep copy T¹ of T⁰ , but omit atomic and function-valued properties, which T¹ will acquire by inheritance. T¹ should also have the same prototype edges as T⁰. Next anchor the prototype chains of T¹ back to T⁰: if a prototype chain in T¹ terminates at a node N¹,extend the chain back to node N⁰, where N⁰ is at the same path in T⁰ as N¹ is in T¹. To give a feel of what goes on, here is a simple example. iii is an initial tree:
Then, after jjj = iii.instantiate():
So, eg, jjj.b.x has value 1, since jjj.b inherits from jjj.a, which in turn inherits from iii.a. jjj.b.y has value 2 for the same reason. Note that iii.b.z has been copied to the instantiation, contrary to the rule that atomic property edges be inherited rather than copied. Well, I didn’t mention every detail of the algorithm. Here is a complete description.