Subj : Re: JS_IsAssigning To : netscape.public.mozilla.jseng From : jmtn@blueyonder.co.uk (James Turner) Date : Fri Aug 29 2003 03:16 am > Why do you need to detect a difference when resolving or getting 'bar' > in foo between 'baz = foo.bar.x;' and 'foo.bar.x = 42;'? Okay, this is going to take some explaining. Possibly, my basic design is a bit wonky. In the example above, 'foo' is actually a JS object associated with a native (C++) class called 'GameEntity'. One of the things the C++ class defines is a map of property names to jsvals, and this acts as a store for the various 'dynamic' (as opposed to hard-coded) props of the gameEntity. Obviously, the JS property getter/setter ops defined for the JSClass associated with GameEntity simply copy jsvals into and out of the map. (I certainly need to do some other things, I suspect, like rooting the jsvals, but that's another issue). Also, when a property is set on the entity, I need to do a bunch of other book-keeping, like adding the GameEntity to a table of recently updated entities, and recording the previous value the property had. Now, to further complicate the issue, GameEntities are created from an 'Archetype' class (another C++ thing), which also has a JSClass, and each Archetype has an associated JSObject, etc, etc. Archetypes track lots of data about their properties, including whether a given prop is visible to all players, the owning player, internal to the server, etc, etc. Now, eventually Archetypes will be creates by reading an IDL-like language at startup, but for now, they're defined in script. So, I do something like this: var myArchetype = new Archetype("cat"); myArchetype.defineProperty("hairyness", 6, "PUBLIC", ... other meta-data for the property .... ); In this code, '6' is the default hairyness of cats. In the C++ code, this jsval goes into the Archetype's table of property descriptions. Now, we create a cat instance. This is done by over-riding the constructor hook in the JSClass (you may recall me asking about that a while back) var cat = new myArchtype(.... args ......); Internally, this creates a GameEntity, and associates it with the 'cat' JSObject. Okay, now someone comes to access the 'hairyness' of 'cat'. In GameEntity's getter impl, the code essential does this: std::string propName = .... from the 'id' jsval ; if (gameEntity->props.find(propName)) { *rv = gameEntity->props[propName]; } else { // value wasn't locally set, use the default *rv = gameEntity->archetpe->props[propName].defaultValue; } This should hopefully reveal the problem. When the property type is an object, and the value has not been locally set on the GameEntity, I end up returning the defaultValue jsval, and then it gets modified - not the desired result! What I would like to do is determine if the jsval I'm returning from my getter is going to be changed, and if so, force it to be locally created on the GameEntity *before* I return it from the getter. I.e, I'd like to be able to do this: std::string propName = .... from the 'id' jsval ; if (gameEntity->props.find(propName)) { *rv = gameEntity->props[propName]; } else { bool isOnLHSofAssignment = ..... ???????; if (isOnLHS) { /* not locally set, but will be modified, so copy it down from the archetype */ gameEntity->props[propName] = gameEntity->archetype->props[propName].defaultValue; *rv = gameEntity->props[propName]; } else // value wasn't locally set, use the default *rv = gameEntity->archetpe->props[propName].defaultValue; } And so, my basic question was basically, how do I compute my 'isOnLHSofAssignment' bool. Now, it's possible everything I'm trying to do is deeply flawed, and I need to switch to JSObjectOps to achieve it .. looking at the above code again, I've got this nagging suspicion I need to be deep-copying jsvals a lot more, to avoid perpetually referencing the same object. Hopefully, this is at least comprehensible. James .