Re: Setting a property in the prototype chain?
On Tue, 12 Apr 2011 07:55:26 +0200, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 11, 2011, at 6:45 PM, Axel Rauschmayer wrote: var obj={}.valueOf.call(obj); // ToObject in case primitive value passed ... {}.valueOf is the same value as Object.prototype.valueOf assuming none of the standard definitions have been over-written. See the comment thread of http://www.wirfs-brock.com/allen/posts/166 for a debate as to which of these forms is more or less optimizable. Object.prototype.valueOf as specified is essentially a call to the internal ToObject operation that wrappers primitive values. I put it in to deal with cases like getDefiningObject(some string, match) In that case, why not just obj = Object(obj); It has the added advantage of not returning the global object for null and undefined, but just a plain new object (although either can be said to be wrong in this case). /L -- Lasse Reichstein - reichsteinatw...@gmail.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Object.prototype.valueOf as specified is essentially a call to the internal ToObject operation that wrappers primitive values. I put it in to deal with cases like getDefiningObject(some string, match) Oh my, I've just consulted the ECMAScript spec and it's true. But isn't that counter-intuitive? - Object.prototype.valueOf: convert to object - String.prototype.valueOf: convert to primitive (for instances of String and primitive strings) - Number.prototype.valueOf: same as above, but for numbers - etc. Even if that can't be fixed any more, there could be a method Object.toObject() with more obvious semantics. I try to avoid expert magic when using a programming language and it seems like a shame that this kind of magic is necessary here ( {} and valueOf()). Greetings, Axel -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Tue, Apr 12, 2011 at 3:57 AM, Lasse Reichstein reichsteinatw...@gmail.com wrote: On Tue, 12 Apr 2011 07:55:26 +0200, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 11, 2011, at 6:45 PM, Axel Rauschmayer wrote: var obj={}.valueOf.call(obj); // ToObject in case primitive value passed ... {}.valueOf is the same value as Object.prototype.valueOf assuming none of the standard definitions have been over-written. See the comment thread of http://www.wirfs-brock.com/allen/posts/166 for a debate as to which of these forms is more or less optimizable. Object.prototype.valueOf as specified is essentially a call to the internal ToObject operation that wrappers primitive values. I put it in to deal with cases like getDefiningObject(some string, match) In that case, why not just obj = Object(obj); It has the added advantage of not returning the global object for null and undefined, For null and undefined, Object.prototype.valueOf throws. It does not return the global object. but just a plain new object (although either can be said to be wrong in this case). /L -- Lasse Reichstein - reichsteinatw...@gmail.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 12, 2011, at 12:57 AM, Lasse Reichstein wrote: In that case, why not just obj = Object(obj); It has the added advantage of not returning the global object for null and undefined, but just a plain new object (although either can be said to be wrong in this case). I used {}.valueOf in order to avoid converting null and undefined to a new object which would then be used as the starting point of the lookup. In ES5 {}.valueOf.call(undefined) doesn't yield the this object. In general, ES5 built-ins do not convert their this parameter to the global object when it is undefined. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Tue, Apr 12, 2011 at 08:41, Allen Wirfs-Brock al...@wirfs-brock.com wrote: In ES5 {}.valueOf.call(undefined) doesn't yield the this object. In general, ES5 built-ins do not convert their this parameter to the global object when it is undefined. FYI http://code.google.com/p/v8/issues/detail?id=1321 https://bugs.webkit.org/show_bug.cgi?id=58338 -- erik ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On 11/04/2011, at 05:14, Mark S. Miller wrote: On Apr 10, 2011, at 22:18 , David Herman wrote: function getDefiningObject(obj, key) { if (!(key in obj)) throw new Error(key + key + not found); while (!obj.hasOwnProperty(key)) That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. And also because that would work for null too, unlike (null).hasOwnProperty( key ) that would throw TypeError: 'null' is not an object (evaluating '(null).hasOwnProperty'), and null is at the end of the prototype chain of all objects... Here's another take on it: function getDefiningObject (o, key) { do { if ( {}.hasOwnProperty.call(o, key) ) break; } while ( o = Object.getPrototypeOf(o) ); return o; } getDefiningObject([1,2], 'length') [1, 2] getDefiningObject([1,2], 'pop') [] getDefiningObject([1,2], 'valueOf') Object getDefiningObject([1,2], 'none') null -- Jorge. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
When is a JavaScript program correct? (was: Setting a property in the prototype chain?)
On Sun, Apr 10, 2011 at 11:21 PM, David Herman dher...@mozilla.com wrote: I wondered if someone was going to make this point. That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. Not if someone mutates Object.prototype.hasOwnProperty or Function.prototype.call. I don't think we need to polish a proof of concept. First, I agree that for the original purpose of this thread, this polishing is irrelevant, so I have changed the subject. But your counter-examples do help to highlight something I've been thinking about. Because of such pervasive mutability, we really haven't had a clear notion of correctness for JavaScript. For normal JavaScript programs, if run after some other code has already mutated that environment's primordials arbitrarily, there's so little they can count on that very few programs could be written correctly under these onerous assumptions[1]. For the notion of correctness in JavaScript to be useful, I think we must allow JavaScript programs to rely on the primordial at least continuing to obey their original contract. However, the use of objects as maps from strings to values is pervasive, e.g., in JSON unserialization, so we should not allow general purpose JavaScript programs to rely on, for example, 'hasOwnProperty' not being overridden. Retrofitting a reasonable theory of correctness after the fact is a tricky exercise. The above theory represents a practical compromise between the assumption that common programs make (primordials obey their original contracts) vs. the assumptions that common programs break (hasOwnProperty is not overridden). Thus, I claim that the original program should not be considered correct, while the modified program should, despite the problematic cases raised by your counter-example. [1] SES initialization freezes the primordials, so SES programs can safely assume they are frozen. But the point I'm making here are not specific to SES. Dave -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: When is a JavaScript program correct? (was: Setting a property in the prototype chain?)
On 11.04.2011 18:07, Mark S. Miller wrote: On Sun, Apr 10, 2011 at 11:21 PM, David Herman dher...@mozilla.com mailto:dher...@mozilla.com wrote: I wondered if someone was going to make this point. That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. Not if someone mutates Object.prototype.hasOwnProperty or Function.prototype.call. I don't think we need to polish a proof of concept. First, I agree that for the original purpose of this thread, this polishing is irrelevant, so I have changed the subject. But your counter-examples do help to highlight something I've been thinking about. Because of such pervasive mutability, we really haven't had a clear notion of correctness for JavaScript. For normal JavaScript programs, if run after some other code has already mutated that environment's primordials arbitrarily, there's so little they can count on that very few programs could be written correctly under these onerous assumptions[1]. For the notion of correctness in JavaScript to be useful, I think we must allow JavaScript programs to rely on the primordial at least continuing to obey their original contract. However, the use of objects as maps from strings to values is pervasive, e.g., in JSON unserialization, so we should not allow general purpose JavaScript programs to rely on, for example, 'hasOwnProperty' not being overridden. Retrofitting a reasonable theory of correctness after the fact is a tricky exercise. The above theory represents a practical compromise between the assumption that common programs make (primordials obey their original contracts) vs. the assumptions that common programs break (hasOwnProperty is not overridden). Thus, I claim that the original program should not be considered correct, while the modified program should, despite the problematic cases raised by your counter-example. As I see it, you address the issue of unstratified meta-programming (note, I take the issue in quotes, since there's no a single meaning whether the unstratified meta-level is so bad). It depends on how to look on the issue. On one hand, why if a user changes the behavior of the `hasOwnProperty` of _his_ object in _his_ program, then the program should be considered as incorrect? The user knows how to handle `hasOwnProperty` for the particular object and the ability to override it is the ability to control unstratified meta-level via simple reassigning to meta-hooks. On the other hand, yes, since we have the ability to modify any JS code via console or even via browser address bar (using pseudo-protocol javascript:), then it can be viewed as the issue and as a security program. But the salvation by the big deal should not be found in making a dynamic language as a completely frozen and static, but in the disallowing of code modification (code injection, code poisoning if you will) via such a simple tools as the console or address bar. Having the ability to inject the needed code via console just makes e.g. browser scripting as just an _addition_ for the server code. This is in case if we have combined client-server application. It's obvious, that if we have some validation tool, then the validation on the client side should be done only as the _convenient addition_. But the same validation will be done on the server, since we understand that the client code can be easily injected (the simplest example e.g. utils.validate = function () { return true; } which always will return positive result). If we have only client-side application, then the user, if breaks some code via injection just breaks his own page and therefore just refuses the convenience we wanted to give him. He doesn't break anything besides his own page. So that's the language is dynamic and allow to change objects in runtime is not in my view about correctness of a program. A programmer, having control of his code, knows how and why he wants to augment and modify his current runtime objects and code. From this viewpoint I don't think we need to disallow modifying of `hasOwnProperty` and similar. Better then to reuse ES5 approach and separate this meta-operation to Object.hasOwnProperty(foo). The fact that a language is static perhaps doesn't cancel the fact that the code still can be injected, etc. So again, IMO a correct program is not about let's freeze everything here. And predefined and predicted contract also relates to statics mostly. In duck typing exactly this contract can be achieved during the runtime -- one line before an object cannot pass the duck-test, on the other line (after some mutations) it already can do this, it satisfies the contract -- and it's achieved not via statics in the language. Dmitry. [1] SES initialization freezes the primordials, so SES programs can safely assume they are frozen. But the point I'm
Re: Setting a property in the prototype chain?
Personally, I prefer Object.getOwnPropertyDescriptor as a property existence test because it doesn't have the reflection the meta-circularity concern. I would write Dave's original function as: function getDefiningObject(obj, key) { var obj={}.valueOf.call(obj); // ToObject in case primitive value passed while (obj) { if (Object.getOwnPropertyDescriptor(obj,key)) return obj; obj = Object.getPrototypeOf(obj); } throw new Error(key + key + not found); } ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: When is a JavaScript program correct? (was: Setting a property in the prototype chain?)
Le 10/04/2011 23:27, Dmitry A. Soshnikov a écrit : On 11.04.2011 18:07, Mark S. Miller wrote: On Sun, Apr 10, 2011 at 11:21 PM, David Herman dher...@mozilla.com mailto:dher...@mozilla.com wrote: I wondered if someone was going to make this point. That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. Not if someone mutates Object.prototype.hasOwnProperty or Function.prototype.call. I don't think we need to polish a proof of concept. First, I agree that for the original purpose of this thread, this polishing is irrelevant, so I have changed the subject. But your counter-examples do help to highlight something I've been thinking about. Because of such pervasive mutability, we really haven't had a clear notion of correctness for JavaScript. For normal JavaScript programs, if run after some other code has already mutated that environment's primordials arbitrarily, there's so little they can count on that very few programs could be written correctly under these onerous assumptions[1]. For the notion of correctness in JavaScript to be useful, I think we must allow JavaScript programs to rely on the primordial at least continuing to obey their original contract. However, the use of objects as maps from strings to values is pervasive, e.g., in JSON unserialization, so we should not allow general purpose JavaScript programs to rely on, for example, 'hasOwnProperty' not being overridden. Retrofitting a reasonable theory of correctness after the fact is a tricky exercise. The above theory represents a practical compromise between the assumption that common programs make (primordials obey their original contracts) vs. the assumptions that common programs break (hasOwnProperty is not overridden). Thus, I claim that the original program should not be considered correct, while the modified program should, despite the problematic cases raised by your counter-example. As I see it, you address the issue of unstratified meta-programming (note, I take the issue in quotes, since there's no a single meaning whether the unstratified meta-level is so bad). It depends on how to look on the issue. On one hand, why if a user changes the behavior of the `hasOwnProperty` of _his_ object in _his_ program, then the program should be considered as incorrect? The user knows how to handle `hasOwnProperty` for the particular object and the ability to override it is the ability to control unstratified meta-level via simple reassigning to meta-hooks. From what I understand of Mark's definition of correctness, this case is not excluded. My understanding is that Mark tries to provide a uniform meaning to answers to questions like is this piece of code /correct/?. I interpret what he said as a program can be considered as correct if it does what we expect it to do within a fresh ES environment. With that interpretation in mind, if the program you want to evaluate redefines Object.prototype.hasOwnProperty and uses consistently this new definition to achieve its goal, then it will be considered correct. One property of this definition must be noted. Appending two independently correct programs may result in an incorrect program (if the first one changes a piece of environment on which the second relies). Most of what you said afterward regarded dynamic validation, I think, which wasn't part of Mark's definition as I understand it (I agree on what you said, though). Cheers, David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: When is a JavaScript program correct? (was: Setting a property in the prototype chain?)
On Sun, Apr 10, 2011 at 5:27 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com wrote: As I see it, you address the issue of unstratified meta-programming (note, I take the issue in quotes, since there's no a single meaning whether the unstratified meta-level is so bad). It depends on how to look on the issue. On one hand, why if a user changes the behavior of the `hasOwnProperty` of _his_ object in _his_ program, then the program should be considered as incorrect? The user knows how to handle `hasOwnProperty` for the particular object and the ability to override it is the ability to control unstratified meta-level via simple reassigning to meta-hooks. Hi Dmitry, your response makes clear two issues I failed to explain well: By program, I do not mean a whole program, i.e., the totality of all code run within a given JS environment. David's original getDefiningObject function and variations are clearly not whole programs. Rather, they are reusable program fragments that could be packaged in reusable libraries, meant to be link into and used from within larger programs that the author of getDefiningObject should not need to know about. Since we're not worried here about programming under mutual suspicion, it could very well be valid for getDefiningObject to assume that various methods are overridden in a contract preserving manner. For example, a Java hashtable that calls a key's hashCode method could be correct. The key's hashCode method might be incorrect, in which case the hastable would function incorrectly, but we'd say that this incorrect behavior is the key's fault rather than the hashtable's fault. We would like a notion of correctness that allows us to reason in a modular manner: A correct composition of individually correct components should yield a correct composite, where the correctness of the composition depends only on the contracts of the components to be composed -- not on their implementation. The Java composite above is incorrect because the key is incorrect. This does not contradict the notion that the hashtable abstraction by itself is correct even though in this case it behaves incorrectly. The problem here is specifically with the methods on Object.prototype vs the pervasive use of objects as string-value maps in JavaScript. What are we to do about getDefiningObject(JSON.parse(str), 'foo') ? Even without mutual suspicion within the program code, we would like to reason about the correctness of this as quantified over all strings, for example, even if the string is received from an external untrusted or unreliable source. On the other hand, yes, since we have the ability to modify any JS code via console or even via browser address bar (using pseudo-protocol javascript:), then it can be viewed as the issue and as a security program. But the salvation by the big deal should not be found in making a dynamic language as a completely frozen and static, but in the disallowing of code modification (code injection, code poisoning if you will) via such a simple tools as the console or address bar. Having the ability to inject the needed code via console just makes e.g. browser scripting as just an _addition_ for the server code. This is in case if we have combined client-server application. It's obvious, that if we have some validation tool, then the validation on the client side should be done only as the _convenient addition_. But the same validation will be done on the server, since we understand that the client code can be easily injected (the simplest example e.g. utils.validate = function () { return true; } which always will return positive result). If we have only client-side application, then the user, if breaks some code via injection just breaks his own page and therefore just refuses the convenience we wanted to give him. He doesn't break anything besides his own page. So that's the language is dynamic and allow to change objects in runtime is not in my view about correctness of a program. A programmer, having control of his code, knows how and why he wants to augment and modify his current runtime objects and code. From this viewpoint I don't think we need to disallow modifying of `hasOwnProperty` and similar. Better then to reuse ES5 approach and separate this meta-operation to Object.hasOwnProperty(foo). The fact that a language is static perhaps doesn't cancel the fact that the code still can be injected, etc. So again, IMO a correct program is not about let's freeze everything here. And predefined and predicted contract also relates to statics mostly. In duck typing exactly this contract can be achieved during the runtime -- one line before an object cannot pass the duck-test, on the other line (after some mutations) it already can do this, it satisfies the contract -- and it's achieved not via statics in the language. Dmitry. [1] SES initialization freezes the primordials, so SES programs can
Re: When is a JavaScript program correct? (was: Setting a property in the prototype chain?)
2011/4/11 Mark S. Miller erig...@google.com: We would like a notion of correctness that allows us to reason in a modular manner: A correct composition of individually correct components should yield a correct composite, where the correctness of the composition depends only on the contracts of the components to be composed -- not on their implementation. The Java composite above is incorrect because the key is incorrect. This does not contradict the notion that the hashtable abstraction by itself is correct even though in this case it behaves incorrectly. The problem here is specifically with the methods on Object.prototype vs the pervasive use of objects as string-value maps in JavaScript. What are we to do about getDefiningObject(JSON.parse(str), 'foo') ? Even without mutual suspicion within the program code, we would like to reason about the correctness of this as quantified over all strings, for example, even if the string is received from an external untrusted or unreliable source. Would you agree with the following?: Given that stackoverflow.com and user-commenting documentation sites ( http://www.php.net/manual/en/ref.pcre.php ) encourage teaching by sharing copy/pasteable snippets of source code, we would like experienced devs to be able to compose succinct snippets that can be shared without an accompanying page of caveats that few will read or know how to check. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: When is a JavaScript program correct? (was: Setting a property in the prototype chain?)
On Mon, Apr 11, 2011 at 2:48 PM, Mike Samuel mikesam...@gmail.com wrote: 2011/4/11 Mark S. Miller erig...@google.com: We would like a notion of correctness that allows us to reason in a modular manner: A correct composition of individually correct components should yield a correct composite, where the correctness of the composition depends only on the contracts of the components to be composed -- not on their implementation. The Java composite above is incorrect because the key is incorrect. This does not contradict the notion that the hashtable abstraction by itself is correct even though in this case it behaves incorrectly. The problem here is specifically with the methods on Object.prototype vs the pervasive use of objects as string-value maps in JavaScript. What are we to do about getDefiningObject(JSON.parse(str), 'foo') ? Even without mutual suspicion within the program code, we would like to reason about the correctness of this as quantified over all strings, for example, even if the string is received from an external untrusted or unreliable source. Would you agree with the following?: Given that stackoverflow.com and user-commenting documentation sites ( http://www.php.net/manual/en/ref.pcre.php ) encourage teaching by sharing copy/pasteable snippets of source code, we would like experienced devs to be able to compose succinct snippets that can be shared without an accompanying page of caveats that few will read or know how to check. Excellent. +1 -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 11, 2011, at 8:58 PM, David Bruant wrote: Le 11/04/2011 21:47, Brendan Eich a écrit : On Apr 11, 2011, at 6:36 PM, Allen Wirfs-Brock wrote: Personally, I prefer Object.getOwnPropertyDescriptor as a property existence test because it doesn't have the reflection the meta-circularity concern. I would write Dave's original function as: function getDefiningObject(obj, key) { var obj={}.valueOf.call(obj); // ToObject in case primitive value passed while (obj) { if (Object.getOwnPropertyDescriptor(obj,key)) return obj; obj = Object.getPrototypeOf(obj); } throw new Error(key + key + not found); } Then the only downside is the pd allocation. Any way to avoid that? Could static analysis help out to detect that the object is not going to be used and consequently avoid the allocation? Of course, but that's a bit much and unless it is adopted by all the bigs, web developers won't count on it and may shy away from the allocation (based on real measurements or premature optimization, doesn't matter). It's not the end of the world to have a pd allocation, of course. But an API that avoids it without analysis might be worth considering. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 11, 2011, at 12:47 PM, Brendan Eich wrote: Then the only downside is the pd allocation. Any way to avoid that? /be Use a GC that supports cheap allocation/recovery of short-lived objects :-) It's probably premature optimization to worry about that one pd allocation without knowing more about the actual use case. I suspect that in many cases, the caller would actually want to get the pd back and so it would probably be best to return: {object: obj, desc: pd}. Of course that has yet another ephemeral object allocation. But really, if you over worry about such allocations you end up doing FORTRAN-like coding. Maybe it's time to work on some JavaScript ephemeral GC benchmarks... Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Le 11/04/2011 22:01, Brendan Eich a écrit : On Apr 11, 2011, at 8:58 PM, David Bruant wrote: Le 11/04/2011 21:47, Brendan Eich a écrit : On Apr 11, 2011, at 6:36 PM, Allen Wirfs-Brock wrote: Personally, I prefer Object.getOwnPropertyDescriptor as a property existence test because it doesn't have the reflection the meta-circularity concern. I would write Dave's original function as: function getDefiningObject(obj, key) { var obj={}.valueOf.call(obj); // ToObject in case primitive value passed while (obj) { if (Object.getOwnPropertyDescriptor(obj,key)) return obj; obj = Object.getPrototypeOf(obj); } throw new Error(key + key + not found); } Then the only downside is the pd allocation. Any way to avoid that? Could static analysis help out to detect that the object is not going to be used and consequently avoid the allocation? Of course, but that's a bit much and unless it is adopted by all the bigs, web developers won't count on it and may shy away from the allocation (based on real measurements or premature optimization, doesn't matter). Actually I was wrong I think. With the introduction of proxies, ES engines won't be able to trivially prevent pd allocation as they could with regular objects just based on static analysis (since static analysis will often fail at saying whether the function will be used with regular objects or proxies as first argument) It's not the end of the world to have a pd allocation, of course. But an API that avoids it without analysis might be worth considering. I think it could be possible if we had a native Object.hasOwnProperty method since that's really what we need here (that's what a static analysis optimization would do internally). David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 11, 2011, at 9:21 PM, David Bruant wrote: Actually I was wrong I think. With the introduction of proxies, ES engines won't be able to trivially prevent pd allocation as they could with regular objects just based on static analysis (since static analysis will often fail at saying whether the function will be used with regular objects or proxies as first argument) Static analysis is conservative, yes. But type inference often can say what exact types |this| and other arguments have. Anyway, this isn't about absolute guarantees unless JS provides an API to query without allocating :-P. I think it could be possible if we had a native Object.hasOwnProperty method since that's really what we need here (that's what a static analysis optimization would do internally). That was left out on purposes during ES3.1/ES5 design to keep things minimal. And of course Proxies built on that API. So probably we should leave this as an optimization challenge (GC, type inference, both if possible). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: When is a JavaScript program correct? (was: Setting a property in the prototype chain?)
Sure, I'll buy that. There's a qualitative difference in how uncooperatively your program is behaving if it mutates primordials to violate their usual contracts, as opposed to simply creating an object that overrides hasOwnProperty, which ought to be allowed. The word theory might be a little loaded, but at least practical advice on how to write reasonable/cooperative code is important for programmers to know how to avoid unintended (i.e., not malicious) interactions between different interacting bits of JS code. I think this is part of what good JS programmers have to learn, and to date there's sadly not enough good, authoritative material with that kind of advice (how not to be anti-modular). Dave On Apr 11, 2011, at 7:07 AM, Mark S. Miller wrote: On Sun, Apr 10, 2011 at 11:21 PM, David Herman dher...@mozilla.com wrote: I wondered if someone was going to make this point. That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. Not if someone mutates Object.prototype.hasOwnProperty or Function.prototype.call. I don't think we need to polish a proof of concept. First, I agree that for the original purpose of this thread, this polishing is irrelevant, so I have changed the subject. But your counter-examples do help to highlight something I've been thinking about. Because of such pervasive mutability, we really haven't had a clear notion of correctness for JavaScript. For normal JavaScript programs, if run after some other code has already mutated that environment's primordials arbitrarily, there's so little they can count on that very few programs could be written correctly under these onerous assumptions[1]. For the notion of correctness in JavaScript to be useful, I think we must allow JavaScript programs to rely on the primordial at least continuing to obey their original contract. However, the use of objects as maps from strings to values is pervasive, e.g., in JSON unserialization, so we should not allow general purpose JavaScript programs to rely on, for example, 'hasOwnProperty' not being overridden. Retrofitting a reasonable theory of correctness after the fact is a tricky exercise. The above theory represents a practical compromise between the assumption that common programs make (primordials obey their original contracts) vs. the assumptions that common programs break (hasOwnProperty is not overridden). Thus, I claim that the original program should not be considered correct, while the modified program should, despite the problematic cases raised by your counter-example. [1] SES initialization freezes the primordials, so SES programs can safely assume they are frozen. But the point I'm making here are not specific to SES. Dave -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
var obj={}.valueOf.call(obj); // ToObject in case primitive value passed Can you explain how this works? - Why {} and not Object.prototype? - I know valueOf as a method that returns a primitive if an object can be converted to one and |this|, otherwise. Oddly enough, this works both in strict mode and in non-strict mode, as explained in the comment. Thanks! Axel -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Apr 11, 2011, at 6:45 PM, Axel Rauschmayer wrote: var obj={}.valueOf.call(obj); // ToObject in case primitive value passed Can you explain how this works? - Why {} and not Object.prototype? - I know valueOf as a method that returns a primitive if an object can be converted to one and |this|, otherwise. Oddly enough, this works both in strict mode and in non-strict mode, as explained in the comment. {}.valueOf is the same value as Object.prototype.valueOf assuming none of the standard definitions have been over-written. See the comment thread of http://www.wirfs-brock.com/allen/posts/166 for a debate as to which of these forms is more or less optimizable. Object.prototype.valueOf as specified is essentially a call to the internal ToObject operation that wrappers primitive values. I put it in to deal with cases like getDefiningObject(some string, match) Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Setting a property in the prototype chain?
As far as I am aware, there is no way to change a property that isn’t at the beginning of the property chain, because the change will create a new property there. Are there plans to change this? It would be nice to have something akin to class methods (without accessing the prototype via some other, e.g. global, reference). -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On 10.04.2011 21:24, Axel Rauschmayer wrote: As far as I am aware, there is no way to change a property that isn’t at the beginning of the property chain, because the change will create a new property there. Are there plans to change this? It would be nice to have something akin to class methods (without accessing the prototype via some other, e.g. global, reference). Inherited accessor property can be change normally via assignment. Also `Object.defineProperty` is a way. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Le 10/04/2011 19:24, Axel Rauschmayer a écrit : As far as I am aware, there is no way to change a property that isn’t at the beginning of the property chain, because the change will create a new property there. Are there plans to change this? It would be nice to have something akin to class methods (without accessing the prototype via some other, e.g. global, reference). The ES5 Object.* API already provides everything you need to manipulate all properties you can find in an object (own or inherited). The lowest-level method to change the value of an own property is Object.defineProperty. This method can also be used to re-configure a property (make it non-configurable, change its enumerablity, change its type (data/accessor), change its writability if it is described by a data property descriptor). For examples, I recommend reading the MDN doc [1]. In order to access a reference to the prototype of an object, you can use Object.getPrototypeOf. Using both, you have enough power to achieve any change you could think of on any property of an object (own or inherited). Few platforms implement both at the moment. See [2] for reference. As Dmitry said, inherited accessor properties could be enough for what you need. David [1] https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty [2] http://kangax.github.com/es5-compat-table/ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
function getDefiningObject(obj, key) { if (!(key in obj)) throw new Error(key + key + not found); while (!obj.hasOwnProperty(key)) obj = Object.getPrototypeOf(obj); return obj; } On Apr 10, 2011, at 10:24 AM, Axel Rauschmayer wrote: As far as I am aware, there is no way to change a property that isn’t at the beginning of the property chain, because the change will create a new property there. Are there plans to change this? It would be nice to have something akin to class methods (without accessing the prototype via some other, e.g. global, reference). -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Exactly what I was looking for. Thanks. On Apr 10, 2011, at 22:18 , David Herman wrote: function getDefiningObject(obj, key) { if (!(key in obj)) throw new Error(key + key + not found); while (!obj.hasOwnProperty(key)) obj = Object.getPrototypeOf(obj); return obj; } On Apr 10, 2011, at 10:24 AM, Axel Rauschmayer wrote: As far as I am aware, there is no way to change a property that isn’t at the beginning of the property chain, because the change will create a new property there. Are there plans to change this? It would be nice to have something akin to class methods (without accessing the prototype via some other, e.g. global, reference). -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
As far as I am aware, there is no way to change a property that isn’t at the beginning of the property chain, because the change will create a new property there. Are there plans to change this? It would be nice to have something akin to class methods (without accessing the prototype via some other, e.g. global, reference). In order to access a reference to the prototype of an object, you can use Object.getPrototypeOf. Right. That's what I didn’t think of: Iterating over the prototype chain until you get to the object that actually owns a given property and then set it there. Thanks, Axel -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
On Sun, Apr 10, 2011 at 6:59 PM, Axel Rauschmayer a...@rauschma.de wrote: Exactly what I was looking for. Thanks. Not exactly... On Apr 10, 2011, at 22:18 , David Herman wrote: function getDefiningObject(obj, key) { if (!(key in obj)) throw new Error(key + key + not found); while (!obj.hasOwnProperty(key)) That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. obj = Object.getPrototypeOf(obj); return obj; } On Apr 10, 2011, at 10:24 AM, Axel Rauschmayer wrote: As far as I am aware, there is no way to change a property that isn’t at the beginning of the property chain, because the change will create a new property there. Are there plans to change this? It would be nice to have something akin to class methods (without accessing the prototype via some other, e.g. global, reference). -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
I wondered if someone was going to make this point. That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. Not if someone mutates Object.prototype.hasOwnProperty or Function.prototype.call. I don't think we need to polish a proof of concept. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Setting a property in the prototype chain?
Exactly what I was looking for. Thanks. Not exactly... True. But it's OK for me as a work-around. That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. IIRC, {} creates a new instance for each invocation. Thus, a better solution would be while (!Object.prototype.hasOwnProperty.call(obj, key)) But I usually prefer David’s more readable version and take the risk of a name clash. -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss