Problem with object properties/hasOwnProperty() in Spidermonkey 78

20 views
Skip to first unread message

Miles

unread,
Feb 2, 2021, 10:51:51 AM2/2/21
to
Hello,

Yet again I'm having to ask for help as I'm clearly being stupid and/or there is something I'm missing...

After an epic effort upgrading our embedding from using Spidermoney 1.8.5 to Spidermonkey 78 it all now seems to be working nicely except for one odd problem reported by a user with object properties.

My embedding defines several classes with properties by using JS_InitClass with JSPropertySpec etc. What I'm doing looks virtually identical to the cookbook example at https://github.com/mozilla-spidermonkey/spidermonkey-embedding-examples/blob/esr78/examples/cookbook.cpp#L703. The only difference I can see is that I use JS_NewObjectWithGivenPrototype instead of JS_NewObjectForConstructor (but I tried changing that and it made no difference)

However, for some reason I don't understand the properties that I define for my class do not return true for Object.prototype.hasOwnProperty() in Spidermonkey 78 but they did in Spidermonkey 1.8.5.
For example I define a Node class with properties x,y,z (and lots more...)

To do the upgrade I have been using all sorts of macros/pre-processor logic so that I can compile using either the old 1.8.5 version or the new 78 version of Spidermonkey until we are sure everything is working.
With the old 1.8.5 engine if I run the following code

var n = new Node(1.1, 2.2, 3.3);
for (a in n)
Message(" Property "+a+": "+n[a]);
Message(" n.hasOwnProperty('x') returns "+n.hasOwnProperty('x'));

I get the output

Property x: 1.100000023841858
Property y: 2.200000047683716
...
n.hasOwnProperty('x') returns true

However, in the new Spidermonkey 78 engine I get

Property x: 1.100000023841858
Property y: 2.200000047683716
...
n.hasOwnProperty('x') returns false

i.e. In the new Spidermonkey 78 engine I can still enumerate over the properties but some some unknown reason the properties are not defined in this class. Presumably the engine thinks they are somehow being defined in the prototype chain somewhere else...
There are differences as to what is exactly being executed in the different engines due to my macros but I'm running the same basic code with JS_InitClass etc.
My class stores private data and I am setting JSCLASS_HAS_PRIVATE
My properties are defined with the flags JSPROP_ENUMERATE|JSPROP_PERMANENT

No doubt I'm (yet again) being stupid and missing something obvious but I can't for the life of me see what the problem is.
Can anybody help?

Many thanks in advance for any assistance

Miles

Jan de Mooij

unread,
Feb 2, 2021, 12:01:03 PM2/2/21
to Miles, dev-tech-...@lists.mozilla.org
On Tue, Feb 2, 2021 at 4:55 PM Miles <miles.t...@arup.com> wrote:

> However, for some reason I don't understand the properties that I define
> for my class do not return true for Object.prototype.hasOwnProperty() in
> Spidermonkey 78 but they did in Spidermonkey 1.8.5.
> For example I define a Node class with properties x,y,z (and lots more...)
>

The properties in the JSPropertySpec that you pass to JS_InitClass (the 7th
argument?) are defined on the prototype chain. Looking at Firefox 3 era
code that hasn't changed and the SpiderMonkey 78 behavior is what I'd
expect.

Are these getters? If not, how do you assign the 1.1/2.2/3.3 properties in
your constructor? Can you post all the relevant code for one of these
properties?

Thanks,
Jan
> _______________________________________________
> dev-tech-js-engine mailing list
> dev-tech-...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
>

Jan de Mooij

unread,
Feb 2, 2021, 12:26:11 PM2/2/21
to Miles, dev-tech-...@lists.mozilla.org
The cookbook example uses getters + JS_SetReservedSlot, I just realized
you're probably following that part too. In that case the getter lives on
n.__proto__ (in your example JS code) and it returns a value stored in a
slot on |n|. Question then is what the old code was doing differently,
maybe it did a JS_SetProperty/JS_DefineProperty somewhere?

Jan

On Tue, Feb 2, 2021 at 6:00 PM Jan de Mooij <jdem...@mozilla.com> wrote:

> On Tue, Feb 2, 2021 at 4:55 PM Miles <miles.t...@arup.com> wrote:
>
>> However, for some reason I don't understand the properties that I define
>> for my class do not return true for Object.prototype.hasOwnProperty() in
>> Spidermonkey 78 but they did in Spidermonkey 1.8.5.
>> For example I define a Node class with properties x,y,z (and lots more...)
>>
>
> The properties in the JSPropertySpec that you pass to JS_InitClass (the
> 7th argument?) are defined on the prototype chain. Looking at Firefox 3 era
> code that hasn't changed and the SpiderMonkey 78 behavior is what I'd
> expect.
>
> Are these getters? If not, how do you assign the 1.1/2.2/3.3 properties in
> your constructor? Can you post all the relevant code for one of these
> properties?
>
> Thanks,
> Jan
>
>
>>

Jan de Mooij

unread,
Feb 2, 2021, 3:25:24 PM2/2/21
to Miles Thornton, dev-tech-...@lists.mozilla.org
On Tue, Feb 2, 2021 at 8:41 PM Miles Thornton <Miles.T...@arup.com>
wrote:

> Could it be something to do with the tiny IDs or perhaps the JSPROP_SHARED
> flag (which no longer exists in Spidermonkey 78)?
>

Ah! There used to be an old hack where properties that were both
JSPROP_SHARED and JSPROP_PERMANENT (= non-configurable) acted like 'own'
properties, exactly what you're seeing here. This was fixed a long time ago
(2011, Firefox 7), not too long after 1.8.5. See these bugs for more info:

https://bugzilla.mozilla.org/show_bug.cgi?id=637994
https://bugzilla.mozilla.org/show_bug.cgi?id=575997

Pretty unfortunate for your use case, where code depended on this :/

(Great work updating from 1.8.5 all the way to 78! That must have been very
painful..)

Jan



> Miles
>
>
>
> *From:* Jan de Mooij <jdem...@mozilla.com>
> *Sent:* 02 February 2021 17:26
> *To:* Miles Thornton <Miles.T...@arup.com>
> *Cc:* dev-tech-...@lists.mozilla.org
> *Subject:* [External] Re: Problem with object properties/hasOwnProperty()
> in Spidermonkey 78
>
>
>
> The cookbook example uses getters + JS_SetReservedSlot, I just realized
> you're probably following that part too. In that case the getter lives on
> n.__proto__ (in your example JS code) and it returns a value stored in a
> slot on |n|. Question then is what the old code was doing differently,
> maybe it did a JS_SetProperty/JS_DefineProperty somewhere?
>
>
>
> Jan
>
>
>
> On Tue, Feb 2, 2021 at 6:00 PM Jan de Mooij <jdem...@mozilla.com> wrote:
>
> On Tue, Feb 2, 2021 at 4:55 PM Miles <miles.t...@arup.com> wrote:
>
> However, for some reason I don't understand the properties that I define
> for my class do not return true for Object.prototype.hasOwnProperty() in
> Spidermonkey 78 but they did in Spidermonkey 1.8.5.
> For example I define a Node class with properties x,y,z (and lots more...)
>
>
>
> The properties in the JSPropertySpec that you pass to JS_InitClass (the
> 7th argument?) are defined on the prototype chain. Looking at Firefox 3 era
> code that hasn't changed and the SpiderMonkey 78 behavior is what I'd
> expect.
>
>
>
> Are these getters? If not, how do you assign the 1.1/2.2/3.3 properties in
> your constructor? Can you post all the relevant code for one of these
> properties?
>
>
>
> Thanks,
>
> Jan
>
>
>
>
> _______________________________________________
> dev-tech-js-engine mailing list
> dev-tech-...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
> <https://secure-web.cisco.com/1SD898HeDJdN5DUbqsALBEtX8jiUmy2IowPAK7TjwVmW3HyTAuzfytwVWtKv4coNWVYCsisgdhuh0YL8MLneoFRepkrG9UKsf4rP28m96KPmecpCbGObMXz_81AX2HKuFxfk-DPZgPNnIuyTE4z5B2kHPPKcQ_lrzJP2b8HEJyRjvRMMZQNgMG6MnjqwNopCXgbcDUewGEy-p4W1elPrbzkb2u81TmHy96Fkwfq4bU8JMOgEPWwDeRAk2frIQ0p4AMPU0_RzgucuWt4KMBfg_liIKO8zicoez-H6kSzuMDNW3FQfihITTprEPT_iWY-Lm/https%3A%2F%2Flists.mozilla.org%2Flistinfo%2Fdev-tech-js-engine>
>
> ____________________________________________________________
> Electronic mail messages entering and leaving Arup business systems are
> scanned for viruses and acceptability of content.
>
Reply all
Reply to author
Forward
0 new messages