global function declarations and predefined global properties

Allen Wirfs-Brock Allen.Wirfs-Brock at microsoft.com
Wed Jul 14 14:49:56 PDT 2010


Ok, I have an  algorithmic "fix" that is limited to step 5 of 10.5 and that is based upon my prose solution:


5.   For each FunctionDeclaration f in code, in source text order do

a.    Let fn be the Identifier in FunctionDeclaration f.

b.    Let fo be the result of instantiating FunctionDeclaration f as described in Clause 13.

c.    Let funcAlreadyDeclared be the result of calling env's HasBinding concrete method passing fn as the argument.

d.    If funcAlreadyDeclared is false, call env's CreateMutableBinding concrete method passing fn and configurableBindings as the arguments.

e.    Else if env is the environment record component of the global environment then

                            i.        Let go be the global object.

                          ii.        Let existingProp be the resulting of calling the [[GetProperty]] internal method of go with argument fn.

                         iii.        If existingProp .[[Configurable]] is true, then

1.    Call the [[DefineOwnProperty]] internal method of go, passing fn, Property Descriptor {[[Value]]: fo, [[Writable]]: true, [[Enumerable]]: true , [[Configurable]]: configurableBindings }, and true as arguments.

                         iv.        Else if IsDataDescrptor(existingProp) and existingProp has attribute values {[[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false}, then

1.    Call the [[DefineOwnProperty]] internal method of go, passing fn, Property Descriptor {[[Value]]: fo}, and true as arguments

                           v.        Else throw a TypeError exception.

f.     Else call env's SetMutableBinding concrete method passing fn, fo, and strict as the arguments.

Here is the prose it is based upon


1) If a global FunctionDeclaration has the same name as an existing property of the global object

    a) If the preexisting property is /configurable/ then the property is redefined using as a data property with FunctionDeclaration default attributes

    b) if the preexisting property is a /non-configurable/ data property whose attributes are the same as FunctionDeclaration default attributes then the value of the property is set to the function object.

    c) otherwise the FunctionDeclaration is ignored and a TypeError exception is thrown.

It's a hack, but I think it gets the job done and is reasonably understandable even if you don't have the prose in front of you.

Going once....

Allen


From: Mark S. Miller [mailto:erights at google.com]
Sent: Tuesday, July 13, 2010 6:26 PM
To: Allen Wirfs-Brock
Cc: Brendan Eich; es5-discuss at mozilla.org
Subject: Re: global function declarations and predefined global properties

On Tue, Jul 13, 2010 at 4:42 PM, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com<mailto:Allen.Wirfs-Brock at microsoft.com>> wrote:
I think there is still a case where there still is a difference between ES3 semantics and either of mine or Mark's formulation of the solution:

//at the global level
function f() {};    //this.f will be configurable: false
eval("function f() {};");  //wants to set this.f to configurable:true but false to true transition is not allowed so throws

I think we must allow this scenario to succeed.  Does anyone think we could get away with letting configurable remain false in this case?  If not, we are [g]oing to have to violate the [[DefineOwnProperty]] attribute transition rules for this specific case.

That really helps clarify the issue, thanks. Above all, we must not violate the [[DefineOwnProperty]] attribute transition rules. The choices I see are:

X) The global definition could leave configurable: true.
Y) The evaled definition could leave configurable: false if it has no choice.
Z) Throw a TypeError.

IIUC, your proposal does #Y because of your step #1b:

b) if the preexisting property is a /non-configurable/ data property whose attributes are the same as FunctionDeclaration default attributes then the value of the property is set to the function object.

Mine did not because <http://wiki.ecmascript.org/doku.php?id=harmony:block_scoped_bindings#new_10.2.1.2.8_object_initializebinding_n_v> Step 5 uses the recorded configurability for N. The change needed is, if the property already exists, to use (the current configurability of the property && the recorded configurability of the binding). Although this makes the future ES-next spec annoyingly more complex, I agree that this change is desirable. And it would bring your informal proposal and my proposed future spec language back into agreement, AFAICT.

It's a bit tricky to be sure, since your informal "set" above suggests entering at [[Put]] rather than [[DefineOwnProperty]]. But since your #1b only applies to a non-configurable own data property, I think the equivalence holds.

From: Mark S. Miller [mailto:erights at google.com<mailto:erights at google.com>]
Sent: Thursday, July 08, 2010 5:11 PM

To: Allen Wirfs-Brock
Cc: Brendan Eich; es5-discuss at mozilla.org<mailto:es5-discuss at mozilla.org>
Subject: Re: global function declarations and predefined global properties


On Thu, Jul 8, 2010 at 4:58 PM, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com<mailto:Allen.Wirfs-Brock at microsoft.com>> wrote:
I didn't see your post before I posted mine.  They may well be the same.  I was trying to express the proposed semantics in "user" concepts rather than spec. concepts so it would be clearer what the impact upon actual JavaScript programmer might be.  If we agree on those then I try to develop a minimal patch to 10.5 step 5 that covers them.  Since this is a correction I think it preferable to let prose do most of the work and not  try to do significant reengineering of the other mechanisms in chapter 10.

Cool. Thanks.

Allen



From: Mark S. Miller [mailto:erights at google.com<mailto:erights at google.com>]
Sent: Thursday, July 08, 2010 4:20 PM
To: Allen Wirfs-Brock
Cc: Brendan Eich; es5-discuss at mozilla.org<mailto:es5-discuss at mozilla.org>

Subject: Re: global function declarations and predefined global properties

On Thu, Jul 8, 2010 at 10:40 AM, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com<mailto:Allen.Wirfs-Brock at microsoft.com>> wrote:
I think a set of user facing semantics that strike a balance between the ES1-3 behavior and the new ES5 functionality would  be something along the lines of:

1) If a global FunctionDeclaration has the same name as an existing property of the global object
    a) If the preexisting property is /configurable/ then the property is redefined using as a data property with FunctionDeclaration default attributes
    b) if the preexisting property is a /non-configurable/ data property whose attributes are the same as FunctionDeclaration default attributes then the value of the property is set to the function object.
    c) otherwise the FunctionDeclaration is ignored and a TypeError exception is thrown.

Since the "error" case is new to ES5 it is reasonable to define it as throwing.  This warns developers that they have stumbled upon something such as declaring a function named undefined that has changed from ES3.

I don't think it would be reasonable as part of an errata to do all the algorithm modifications to chapter 10 that would be necessary to express the above.  However, I do think we could slip the above rules as prose into step 5 of 10.5.

In what ways is this informally stated semantics observably different from the one I suggested? I can think of one[*], but I'm curious which you may have in mind? Of these differences, do you prefer the semantics you're suggesting, or are we only discussing how to amend the text of the ES5 spec to suggest an agreed semantics? As long as the observable semantics amounts to the same thing, any agreeable way of revising the ES5 spec text to reflect this semantics at this late date is fine by me.


[*] The semantics of my earlier suggestion, for this case, amounts to 10.5 step 5 doing

  If (not funcDeclared) {
    global.[[DefineOwnProperty]](FName,
        {   [[Value]]: undefined, [[Writable]]: true,
            [[Enumerable]]: true, [[Configurable]]: configValue },
        true);
  }
(i.e., by calling CreateMutableBinding(FName, configValue) in step 5.d)

followed by calling

    global.[[DefineOwnProperty]](FName,
        {   [[Value]]: func, [[Writable]]: true,
            [[Enumerable]]: true, [[Configurable]]: configValue },
        true);
(i.e., what would have been a call to InitializeBinding(FName, func) in step 5.e)


AFAICT, the only observable difference is the one you already agreed to in a previous context: If the global object is non extensible and the global object does not yet have a property named FName, then we should also throw a TypeError. But I may have missed something. Do you agree that we need to throw in this case? Does anyone see any other observable differences?


--
    Cheers,
    --MarkM



--
    Cheers,
    --MarkM



--
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es5-discuss/attachments/20100714/24bf93cf/attachment-0001.html>


More information about the es5-discuss mailing list