API for permanent property maps

NEW
Unassigned

Status

()

Core
JavaScript Engine
--
enhancement
12 years ago
4 years ago

People

(Reporter: Igor Bukanov, Unassigned)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

12 years ago
Suppose an embedding wants to define a class for objects with fixed number of known in advance properties where properties are typically initialized in the constructor. Currently there are 3 options to do that.

1. One can call in the constructor JS_DefineProperty() to set all the properties. But as bug 347248 has shown this is slow. As a workaround class can initialize properties lazily (a solution from bug  347248), but that require a lot of code to write proper resolve and enumeration hooks.

2. One can define getter and setter for each property in the prototype object. But this is again messy since the values for properties have to be stored somewhere.

3. One can redefine JSObjectOps to get full control on property definitions. But that is way too heavy.

Thus I suggest to add an option to JSClass to declare that each instance of the class would have at least the given set of fixed properties and the properties should always be mapped to fixed property indexes. With such API the problem of initialization becomes trivial. For example, for Error class one would need to add  to the class initializer:

static JSStaticPropertyMapEntry errorStaticMap[] = { 
    {js_message_str, JSPROP_ENUMERATE },
    {js_fileName_str, JSPROP_ENUMERATE},
    {js_lineNumber_str, JSPROP_ENUMERATE},
    {js_stack_str, JSPROP_ENUMERATE | JSPROP_LAZY},
};

JSExtendedClass  js_ErrorClass {
...
  errorStaticMap,
  error_lazy_prop_hook
};

where error_lazy_prop_hook must be provided since there is one lazy property and will look like:

error_lazy_prop_hook(JSContext *cx, JSObject *obj, uintN propertyIndex)
{
    jsval stackStrVal;
    
    JS_ASSERT(propertyIndex == 3); /* only stack is lazy */
    buildStackVal();
    JS_SetIndexedProp(cx, obj, propertyIndex, propertyIndex);
}


The constructor code itself will contain:

    JS_SetIndexedProp(cx, obj, 0, messageValue);
    JS_SetIndexedProp(cx, obj, 1, fileNameValue);
    JS_SetIndexedProp(cx, obj, 2, lineNumberValue);

This is fast since it the implementation translates the index into internal permanent slot and set the value without any locking etc.

Such API can be farther extended to get a full control on indexed properties if a hook can be provided to set/get the property given the index.
> 2. One can define getter and setter for each property in the prototype object.
> But this is again messy since the values for properties have to be stored
> somewhere.

To explain the original design a bit more: almost all Netscape 2 native objects reflected peer layout data structures (form elements, e.g.), connected via private data slots in JS objects.  The storage was elsewhere, in other words, and already allocated.  The prototype getters and setters (really class getters and setters, to share common prolog and epilog code) just reflected the data.

Prototype-based properties still win in many cases, but lazy reflection of per-instance properties has its place too.  The API just never gave it its due.

/be
(Assignee)

Updated

4 years ago
Assignee: general → nobody
You need to log in before you can comment on or make changes to this bug.