Closed Bug 131348 Opened 23 years ago Closed 23 years ago

|var obj; for (item in obj) {}| causes error

Categories

(Core :: JavaScript Engine, defect)

x86
All
defect
Not set
normal

Tracking

()

VERIFIED FIXED
mozilla1.0

People

(Reporter: pschwartau, Assigned: khanson)

References

Details

(Keywords: relnote, Whiteboard: [Have filed bug 136893 on Rhino for same issue])

Attachments

(1 file)

Reported by crock@statesoftware.com: We tracked down our problem with 0.9.9. It was in a for..in statement: for (item in object) { .... } In this case, the value of |object| was |undefined|. In most implementations, this causes the for loop to finish immediately. On 0.9.9, this causes an error. I am not sure that what 0.9.9 is doing is wrong, but it will have an impact on portability. If I were you, I would go back to the friendlier behavior.
Try this javascript: URL javascript: for (item in undefined) {}; alert("Hi"); In NN4.7 and IE6, this succeeds and you get the alertbox. In Mozilla, you get no alertbox, but an error in the JS Console: Error: undefined has no properties Source File: javascript: for (item in undefined) {}; alert("Hi"); Line: 1 On the face of it, this is per spec. But I will let the developers decide what they think of this one. NOTE: If you try the reported line, NONE of the three browsers shows the alertbox: javascript: for (item in obj) {}; alert("Hi"); So I'm not sure what portability issues there are here -
Here is the spec; ECMA-262 Edition 3 Final. The key step is number 5. 11.8.7 The in operator The production RelationalExpression : RelationalExpression in ShiftExpression is evaluated as follows: 1. Evaluate RelationalExpression. 2. Call GetValue(Result(1)). 3. Evaluate ShiftExpression. 4. Call GetValue(Result(3)). 5. If Result(4) is not an object, throw a TypeError exception. 6. Call ToString(Result(2)). 7. Call the [[HasProperty]] method of Result(4) with parameter Result(6). 8. Return Result(7).
Assignee: rogerl → khanson
I suppose this might be what crock@statesoftware.com is running into: javascript: var obj; for (item in obj) {}; alert("Hi"); That is, |obj| has been declared, but not initialized. Here are the results from the various browsers: NN4.7, IE6 : both show the alertbox. No error. Mozilla : no alertbox, and this error: Error: undefined has no properties Source File: javascript: var obj; for (item in obj) {}; alert("Hi"); Line: 1
Summary: for (item in obj) {} causes error if |obj| is undefined → |var obj; for (item in obj) {}| causes error
This was a purposeful change a month or two back to comply with the part of the spec Phil cites...
ECMA 262 Edition 3 12.6.4 step 3 leads to 9.9, where the first two table entries specify that a TypeError be thrown. A fix for this standards compliance bug shipped in mozilla0.9.9. Cc'ing waldemar in case the working group might reconsider in light of the longstanding Netscape (at least; dunno about IE) behavior. /be
/me is red-faced and resolves to read the bug, not just the nearest bugmail message in his Inbox... /be
FWIW, this was changed in bug 121744 - "JS should error on |for(i in undefined)|, |for(i in null)|"
*** Bug 136113 has been marked as a duplicate of this bug. ***
Phil: it looks like you're quoting the standard portion dealing with the binary |in| operator, which tests the existence of a property (|if ("p" in o)|), rather than the portion dealing with object enumeration (| for (p in o)|). I don't have my ECMA to hand, so I can't offer a better quote at the moment.
The "standards compliance fix" in Mozilla 0.9.9 might be a disaster to existing JavaScript code. In my project, I will have to manually change more than one hundred lines in about twenty JavaScript files. My hope is that this change will not be included in any official Netscape 6.x release.
Here is the ECMA spec regarding |for-in| 12.6.4 The for-in Statement The production IterationStatement : for ( LeftHandSideExpression in Expression ) Statement is evaluated as follows: 1. Evaluate the Expression. 2. Call GetValue(Result(1)). 3. Call ToObject(Result(2)). 4. Let V = empty. 5. Get the name of the next property of Result(3) that doesn’t have the DontEnum attribute. If there is no suchproperty, go to step 14. 6. Evaluate the LeftHandSideExpression ( it may be evaluated repeatedly). 7. Call PutValue(Result(6), Result(5)). 8. Evaluate Statement. 9. If Result(8).value is not empty, let V = Result(8).value. 10. If Result(8).type is break and Result(8).target is in the current label set, go to step 14. 11. If Result(8).type is continue and Result(8).target is in the current label set, go to step 5. 12. If Result(8) is an abrupt completion, return Result(8). 13. Go to step 5. 14. Return (normal, V, empty). The production IterationStatement : for ( var VariableDeclarationNoIn in Expression )Statement is evaluated as follows: 1. Evaluate VariableDeclarationNoIn. 2. Evaluate Expression. 3. Call GetValue(Result(2)). 4. Call ToObject(Result(3)). 5. Let V = empty. 6. Get the name of the next property of Result(4) that doesn’t have the DontEnum attribute. If there is no such property, go to step 15. 7. Evaluate Result(1) as if it were an Identifier; see 11.1.2 (yes, it may be evaluated repeatedly). 8. Call PutValue(Result(7), Result(6)). 9. Evaluate Statement. 10. If Result(9).value is not empty, let V = Result(9).value. 11. If Result(9).type is break and Result(9).target is in the current label set, go to step 15. 12. If Result(9).type is continue and Result(9).target is in the current label set, go to step 6. 13. If Result(8) is an abrupt completion, return Result(8). 14. Go to step 6. 15. Return (normal, V, empty). The mechanics of enumerating the properties (step 5 in the first algorithm, step 6 in the second) is implementation-dependent. The order of enumeration is defined by the object. Properties of the object being enumerated may be deleted during enumeration. If a property that has not yet been visited during enumeration is deleted, then it will not be visited. If new properties are added to the object being enumerated during enumeration, the newly added properties are not guaranteed to be visited in the active enumeration. Enumerating the properties of an object includes enumerating properties of its prototype, and the prototype of the prototype, and so on, recursively; but a property of a prototype is not enumerated if it is “shadowed” because some previous object in the prototype chain has a property with the same name.
Mike: thanks for catching my misquote above. I hadn't realized there were two different senses for |in|. But as Brendan noted above: > ECMA 262 Edition 3 12.6.4 step 3 leads to 9.9, where the first two > table entries specify that a TypeError be thrown. A fix for this > standards compliance bug shipped in mozilla0.9.9. > Cc'ing waldemar in case the working group might reconsider in light > of the longstanding Netscape (at least; dunno about IE) behavior. > /be Here is a synopsis. Taken from bug 121744, where we fixed this bug: "JS should error on |for(i in undefined)|, |for(i in null)| " 12.6.4 The for-in Statement The production IterationStatement : for ( LeftHandSideExpression in Expression ) Statement is evaluated as follows: 1. Evaluate the Expression. 2. Call GetValue(Result(1)). 3. Call ToObject(Result(2)). ... 9.9 ToObject Input Type : Result Undefined : Throw a TypeError exception. Null : Throw a TypeError exception. ...
-------------------------- SUMMARY ------------------------------- In bug 121744, we fixed this bug: "JS should error on |for(i in undefined)|, |for(i in null)| " We were right to do this from a standards point of view, since the ECMA-262 standard specifies this behavior (see above). But have we broken many web pages by doing this? That seems to be the issue now. The fact is, we have changed the behavior of JS from both NN4.7 and IE, where such statements do not produce errors. To see this, try these javascript: URLS javascript: for(i in undefined){}; alert('Done'); javascript: for(i in null){}; alert('Done'); javascript: var obj; for(i in obj){}; alert('Done'); In NN4.7 and IE6, you get the alert('Done') on each of these. In Mozilla/N6, you don't get any alert, but rather these errors: Error: undefined has no properties Error: null has no properties Error: undefined has no properties
I'm not sure it's worth fixing this bug, since we may make this behavior legitimate in ECMAScript Edition 4. I posed this issue to the ECMA group and will see what response I get.
Based on Waldemar's Comment #14, should we reopen bug 121744 and undo the fix we made there?
We (the ECMA group) are leaning towards treating this as a bug in the standard. What other related cases are there? Phil: How does the in operator behave on the various implementations?
Standards are written by people, and should serve people.
The change made to comply with the standard as written is easily undone. Let's get this right for mozilla1.0 -- I'm preapproving and taking the liberty of targeting. To undo, just 'cvs up -j3.98 -j3.97 jsinterp.c', test, review, and check in. /be
Keywords: mozilla1.0+
Target Milestone: --- → mozilla1.0
I have just tested the effect of 'cvs up -j3.98 -j3.97 jsinterp.c' against the JS testsuite on Linux. It only causes one new failure: Testcase ecma_3/Statements/regress-121744.js failed: Bug Number 121744 STATUS: JS should error on |for(i in undefined)|, |for(i in null)| Failure messages were: Section 1 of test - Expected value 'TypeError', Actual value 'Did not generate ANY error!!!' etc. etc. But this is to be expected. Recall bug 121744 is where we instituted the change to comply with the standard. I will now modify the test to expect no error, and add annotations both to the test and bug 121744.
this is currently release noted, please be sure to update the release note for mozilla1.0
Keywords: relnote
I have: 1. Modified the testcase for bug 121744 to run only in Rhino, not SpiderMonkey 2. Added a testcase for the current bug: mozilla/js/tests/ecma_3/Statements/regress-131348.js 3. Filed bug 136893 to see if Rhino wants to follow SpiderMonkey on this, or continue to conform to the ECMA-262 Edition 3 spec 4. I will relase-note this for Mozilla 1.0 once the current bug is resolved.
I've noted this in the Mozilla 1.0 Release Notes Tracking Bug. See http://bugzilla.mozilla.org/show_bug.cgi?id=133795#c13 timeless: thank you for pointing out the need for this!
Backing out patch #66477
Comment on attachment 79841 [details] [diff] [review] Reverse of Patch 66477 for bug #121744 r=shaver.
Attachment #79841 - Flags: review+
Comment on attachment 79841 [details] [diff] [review] Reverse of Patch 66477 for bug #121744 sr=brendan@mozilla.org -- khanson, please land ASAP on the trunk and petition drivers for approval to get this into the MOZILLA_1_0_BRANCH. Thanks, /be
Attachment #79841 - Flags: superreview+
We need to get this in. I've tested the effect of this in Comment #19 - looks good. NOTE: for some reason, I cannot apply the patch provided in Comment #23: [//d/JS_EXP/mozilla/js/src] patch < 131348.patch patch unexpectedly ends in middle of line patch: **** Only garbage was found in the patch input. This happens to me both on Linux and WinNT; don't know what's going wrong.
Committed to trunk.
Comment on attachment 79841 [details] [diff] [review] Reverse of Patch 66477 for bug #121744 changed line feeds
Comment on attachment 79841 [details] [diff] [review] Reverse of Patch 66477 for bug #121744 a=asa (on behalf of drivers) for checkin to the 1.0 branch
Attachment #79841 - Flags: approval+
Brendan, I am having difficulty checking this into the Bracnh. It has all the necessary aprovals. Could you please check it in. Thanks, Kenton
I checked the patch into the 1.0 branch. Patrick, could you give Kenton a hand with MacCVS? Thanks. /be
Status: NEW → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
Verified Fixed on the trunk and the Mozilla 1.0.0 branch. Tried these variations: javascript: for (item in null) {}; alert("Hi"); javascript: for (item in undefined) {}; alert("Hi"); javascript: var obj; for (item in obj) {}; alert("Hi"); Got the alertbox every time, and no errors in the JS Console -
Status: RESOLVED → VERIFIED
Whiteboard: [Have filed bug 136893 on Rhino for same issue]
Flags: testcase+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: