Bug 133532 - REGRESSION prototype chain ignored iterating properties of global object
Summary: REGRESSION prototype chain ignored iterating properties of global object
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL: http://test.saurik.com/apple/protocha...
Keywords:
Depends on:
Blocks:
 
Reported: 2014-06-04 19:24 PDT by Jay Freeman (saurik)
Modified: 2014-06-06 00:53 PDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jay Freeman (saurik) 2014-06-04 19:24:58 PDT
To put this upfront: this issue affects JavaScriptCore on iOS 8.0 and Mac OS X 10.10. The functionality in question works on iOS 2-7 and OS X 10.5-9. I was told by an Apple engineer at WWDC to file a bug here and start the summary with "REGRESSION". I attempted to replicate this issue in a browser, and it seems my attempt "fails" on older versions (iOS 6/7, OS X 10.8/9), but I could see many (maybe silly/wrong) reasons why this might be different.

So, here's an example interaction (using a JavaScript REPL that runs everything through JavaScriptCore). I am going to assign the prototype of the global object and then walk to a variable. My REPL prints objects using JSObjectCopyPropertyNames, but I have also provided code using a for/in loop to get the same data into an array (note the REPL shows the array as an object). Note that I am using the global object: the scenario works for other objects.

I have filed two separate bugs because I was asked to do so by Oliver. This bug is in relation to iterating the properties inherited by prototype (here shown using a for/in loop).

Here is the working behavior from the old version of JavaScriptCore:

cy# a = {}; this.__proto__ = a; a.f = 5; this
{a:{f:5},f:5}
cy# this.f
5
cy# c = []; for (x in this) c.push(x); c
{0:"a",1:"c",2:"f"}

Here is the broken behavior from the new version of JavaScriptCore:

cy# a = {}; this.__proto__ = a; a.f = 5; this
{a:{f:5}}
cy# this.f
5
cy# c = []; for (x in this) c.push(x); c
{0:"a",1:"c"}

FWIW, if there is some different way of doing this, if this was never supposed to have worked, etc. I would be more than happy to be told "do something different". I don't see myself why this shouldn't work, however, and I've been doing this without issue now on JavaScriptCore for over five years.
Comment 1 Jay Freeman (saurik) 2014-06-06 00:53:05 PDT
To make certain this is clear when this bug is evaluated (due to some confusion on #133531), the behavior in my code is to use JSContextGetGlobalObject to get the global object (which I guess is now a JSProxy?), then use JSObjectGetPrototype in a loop to find the top-most prototype, and finally to use JSObjectSetPrototype on the final not-NULL result. I demonstrated the change in behavior using JavaScript in this bug, but I am actually working at the level of JavaScriptCore's API.