Exception message for expressions with multiple bracket accesses is inconsistent...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Oct 2016 06:31:40 +0000 (06:31 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Oct 2016 06:31:40 +0000 (06:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163426

Patch by Joseph Pecoraro <pecoraro@apple.com> on 2016-10-13
Reviewed by Geoffrey Garen.

JSTests:

* ChakraCore/test/Error/CallNonFunction_3.baseline-jsc:
* ChakraCore/test/Object/null.baseline-jsc:
* stress/exception-in-to-property-key-should-be-handled-early.js:
Better exception messages.

LayoutTests/imported/w3c:

* web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime-expected.txt:
* web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id-expected.txt:
* web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit-expected.txt:
* web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime-expected.txt:
* web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track-expected.txt:
Better expection messages.

Source/JavaScriptCore:

* bytecompiler/NodesCodegen.cpp:
(JSC::BracketAccessorNode::emitBytecode):
It matters where emitExpressionInfo is called since it gathers
info about where we are in the instruction stream. We need to
emit it before the bytecode that we want to associate the data
with. In this case, before the getById / getByVal.

LayoutTests:

* js/exception-expression-offset-expected.txt:
* js/script-tests/exception-expression-offset.js:
(testException):
Correct existing tests and add new tests for multiple and intermixed
dot / bracket accesses.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207326 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
JSTests/ChakraCore/test/Error/CallNonFunction_3.baseline-jsc
JSTests/ChakraCore/test/Object/null.baseline-jsc
JSTests/ChangeLog
JSTests/stress/exception-in-to-property-key-should-be-handled-early.js
LayoutTests/ChangeLog
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track-expected.txt
LayoutTests/js/exception-expression-offset-expected.txt
LayoutTests/js/script-tests/exception-expression-offset.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

index 12c55ec..277cc78 100644 (file)
@@ -12,7 +12,7 @@ TypeError (undefined): null is not a constructor (evaluating 'new obj[0]()')
 TypeError (undefined): obj[1] is not a function. (In 'obj[1]()', 'obj[1]' is 1)
 TypeError (undefined): 1 is not a constructor (evaluating 'new obj[1]()')
 TypeError (undefined): null is not an object (evaluating 'n[1]')
-TypeError (undefined): null is not an object (evaluating 'n')
+TypeError (undefined): null is not an object (evaluating 'new n[1]')
 TypeError (undefined): null is not an object (evaluating 'n.prop')
 TypeError (undefined): null is not an object (evaluating 'new n.prop')
 TypeError (undefined): n is not a function. (In 'n()', 'n' is null)
index 924dd52..f38405a 100644 (file)
@@ -1,37 +1,37 @@
 0 null is not an object (evaluating 'x.y')
 1 null is not an object (evaluating 'x.y = 5')
 2 null is not an object (evaluating 'delete x.y')
-3 null is not an object (evaluating 'x')
+3 null is not an object (evaluating 'x[6]')
 4 null is not an object (evaluating 'x[6] = 7')
 5 null is not an object (evaluating 'delete x[6]')
 6 undefined is not an object (evaluating 'x.y')
 7 undefined is not an object (evaluating 'x.y = 5')
 8 undefined is not an object (evaluating 'delete x.y')
-9 undefined is not an object (evaluating 'x')
+9 undefined is not an object (evaluating 'x[6]')
 10 undefined is not an object (evaluating 'x[6] = 7')
 11 undefined is not an object (evaluating 'delete x[6]')
 12 null is not an object (evaluating 'a[0].y')
 13 null is not an object (evaluating 'a[0].y = 5')
 14 null is not an object (evaluating 'delete a[0].y')
-15 null is not an object (evaluating 'a[0]')
+15 null is not an object (evaluating 'a[0][6]')
 16 null is not an object (evaluating 'a[0][6] = 7')
 17 null is not an object (evaluating 'delete a[0][6]')
 18 undefined is not an object (evaluating 'a[0].y')
 19 undefined is not an object (evaluating 'a[0].y = 5')
 20 undefined is not an object (evaluating 'delete a[0].y')
-21 undefined is not an object (evaluating 'a[0]')
+21 undefined is not an object (evaluating 'a[0][6]')
 22 undefined is not an object (evaluating 'a[0][6] = 7')
 23 undefined is not an object (evaluating 'delete a[0][6]')
 24 null is not an object (evaluating 'o.z.y')
 25 null is not an object (evaluating 'o.z.y = 5')
 26 null is not an object (evaluating 'delete o.z.y')
-27 null is not an object (evaluating 'o.z')
+27 null is not an object (evaluating 'o.z[6]')
 28 null is not an object (evaluating 'o.z[6] = 7')
 29 null is not an object (evaluating 'delete o.z[6]')
 30 undefined is not an object (evaluating 'o.z.y')
 31 undefined is not an object (evaluating 'o.z.y = 5')
 32 undefined is not an object (evaluating 'delete o.z.y')
-33 undefined is not an object (evaluating 'o.z')
+33 undefined is not an object (evaluating 'o.z[6]')
 34 undefined is not an object (evaluating 'o.z[6] = 7')
 35 undefined is not an object (evaluating 'delete o.z[6]')
 count: 36 total: 36
index 84b8700..a464212 100644 (file)
@@ -1,3 +1,15 @@
+2016-10-13  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Exception message for expressions with multiple bracket accesses is inconsistent / incorrect
+        https://bugs.webkit.org/show_bug.cgi?id=163426
+
+        Reviewed by Geoffrey Garen.
+
+        * ChakraCore/test/Error/CallNonFunction_3.baseline-jsc:
+        * ChakraCore/test/Object/null.baseline-jsc:
+        * stress/exception-in-to-property-key-should-be-handled-early.js:
+        Better exception messages.
+
 2016-10-13  Mark Lam  <mark.lam@apple.com>
 
         Fix Array.prototype.splice ES6 compliance.
index e511d03..ad15335 100644 (file)
@@ -133,7 +133,7 @@ function shouldThrow(func, message) {
     if (called)
         throw new Error(called);
     toStringCalled = false;
-    shouldThrow(function () { test(null, 20, propertyKey); }, "TypeError: null is not an object (near '...for (var i = 0; i < length; ++i)...')");
+    shouldThrow(function () { test(null, 20, propertyKey); }, "TypeError: null is not an object (evaluating 'array[property]')");
     if (toStringCalled)
         throw new Error("toString is called.");
 }());
index ceea157..8b06dd5 100644 (file)
@@ -1,3 +1,16 @@
+2016-10-13  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Exception message for expressions with multiple bracket accesses is inconsistent / incorrect
+        https://bugs.webkit.org/show_bug.cgi?id=163426
+
+        Reviewed by Geoffrey Garen.
+
+        * js/exception-expression-offset-expected.txt:
+        * js/script-tests/exception-expression-offset.js:
+        (testException):
+        Correct existing tests and add new tests for multiple and intermixed
+        dot / bracket accesses.
+
 2016-10-13  Alex Christensen  <achristensen@webkit.org>
 
         Hosts of URLs with non-special schemes should be case-sensitive, and non-ASCII characters in such hosts should be punycode-encoded
index 47169ba..d97d780 100644 (file)
@@ -1,3 +1,17 @@
+2016-10-13  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Exception message for expressions with multiple bracket accesses is inconsistent / incorrect
+        https://bugs.webkit.org/show_bug.cgi?id=163426
+
+        Reviewed by Geoffrey Garen.
+
+        * web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime-expected.txt:
+        * web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id-expected.txt:
+        * web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit-expected.txt:
+        * web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime-expected.txt:
+        * web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track-expected.txt:
+        Better expection messages.
+
 2016-10-13  Alex Christensen  <achristensen@webkit.org>
 
         Hosts of URLs with non-special schemes should be case-sensitive, and non-ASCII characters in such hosts should be punycode-encoded
index 2428dd8..1d958ab 100644 (file)
@@ -5,85 +5,109 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 Testing 'undefined.a++'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined.a')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined.a')"
 
 Testing '++undefined.a'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined.a')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined.a')"
 
 Testing 'undefined[0]++'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined[0]')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined[0]')"
 
 Testing '++undefined[1]'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined[1]')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined[1]')"
 
 Testing 'undefined.b'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined.b')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined.b')"
 
 Testing 'undefined[0]'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined[0]')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined[0]')"
 
 Testing 'undefined.b += 1'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined.b')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined.b')"
 
 Testing 'undefined[0] += 1'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined[0]')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined[0]')"
 
 Testing 'undefined()'
-FAIL ex.message == "'undefined' is not a function (evaluating 'undefined()')" should be true. Was false.
+PASS ex.message is "undefined is not a function. (In 'undefined()', 'undefined' is undefined)"
 
 Testing 'new undefined()'
-FAIL ex.message == "'undefined' is not a constructor (evaluating 'new undefined()')" should be true. Was false.
+PASS ex.message is "undefined is not a constructor (evaluating 'new undefined()')"
 
 Testing '({}).b()'
-FAIL ex.message == "'undefined' is not a function (evaluating '({}).b()')" should be true. Was false.
+PASS ex.message is "({}).b is not a function. (In '({}).b()', '({}).b' is undefined)"
 
 Testing 'new {}.b()'
-FAIL ex.message == "'undefined' is not a constructor (evaluating 'new {}.b()')" should be true. Was false.
+PASS ex.message is "undefined is not a constructor (evaluating 'new {}.b()')"
 
 Testing '1()'
-FAIL ex.message == "'1' is not a function (evaluating '1()')" should be true. Was false.
+PASS ex.message is "1 is not a function. (In '1()', '1' is 1)"
 
 Testing 'new 1()'
-FAIL ex.message == "'1' is not a constructor (evaluating 'new 1()')" should be true. Was false.
+PASS ex.message is "1 is not a constructor (evaluating 'new 1()')"
 
 Testing 'throw { message : 'thrown object' }'
-PASS ex.message == "thrown object" is true
+PASS ex.message is "thrown object"
 
 Testing '1 in undefined'
-FAIL ex.message == "'undefined' is not a valid argument for 'in' (evaluating '1 in undefined')" should be true. Was false.
+PASS ex.message is "undefined is not an Object. (evaluating '1 in undefined')"
 
 Testing '1 instanceof undefined'
-FAIL ex.message == "'undefined' is not a valid argument for 'instanceof' (evaluating '1 instanceof undefined')" should be true. Was false.
+PASS ex.message is "Right hand side of instanceof is not an object"
 
 Testing 'for (undefined.b in [1]) {}'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined.b')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined.b')"
 
 Testing 'for (undefined[0] in [1]) {}'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined[0]')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined[0]')"
 
 Testing 'undefined.a = 5'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined.a = 5')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined.a = 5')"
 
 Testing 'undefined[0] = 5'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined[0] = 5')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined[0] = 5')"
 
 Testing '({b:undefined}).b.a = 5'
-FAIL ex.message == "'undefined' is not an object (evaluating '({b:undefined}).b.a = 5')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating '({b:undefined}).b.a = 5')"
 
 Testing '({b:undefined}).b[0] = 5'
-FAIL ex.message == "'undefined' is not an object (evaluating '({b:undefined}).b[0] = 5')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating '({b:undefined}).b[0] = 5')"
 
 Testing 'undefined.a += 5'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined.a')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined.a')"
 
 Testing 'undefined[0] += 5'
-FAIL ex.message == "'undefined' is not an object (evaluating 'undefined[0]')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating 'undefined[0]')"
 
 Testing '({b:undefined}).b.a += 5'
-FAIL ex.message == "'undefined' is not an object (evaluating '({b:undefined}).b.a')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating '({b:undefined}).b.a')"
 
 Testing '({b:undefined}).b[0] += 5'
-FAIL ex.message == "'undefined' is not an object (evaluating '({b:undefined}).b[0]')" should be true. Was false.
+PASS ex.message is "undefined is not an object (evaluating '({b:undefined}).b[0]')"
+
+Testing '[].a.b.x'
+PASS ex.message is "undefined is not an object (evaluating '[].a.b')"
+
+Testing '[]['a']['b'].x'
+PASS ex.message is "undefined is not an object (evaluating '[]['a']['b']')"
+
+Testing '[].a['b'].x'
+PASS ex.message is "undefined is not an object (evaluating '[].a['b']')"
+
+Testing '[]['a'].b.x'
+PASS ex.message is "undefined is not an object (evaluating '[]['a'].b')"
+
+Testing 'func(undefined.x)'
+PASS ex.message is "undefined is not an object (evaluating 'undefined.x')"
+
+Testing 'func(null.x)'
+PASS ex.message is "null is not an object (evaluating 'null.x')"
+
+Testing 'func(undefined[0])'
+PASS ex.message is "undefined is not an object (evaluating 'undefined[0]')"
+
+Testing 'func(null[0])'
+PASS ex.message is "null is not an object (evaluating 'null[0]')"
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 149d26f..82345bf 100644 (file)
@@ -9,34 +9,46 @@ function testException(code, errorStart, errorCaret, errorEnd, message) {
     } catch (e) {
         ex = e;
         // begin/caret/end are not presently exposed in a web facing interface, so cannot be directly checked.
-        shouldBeTrue('ex.message == "' + message +'"');
+        shouldBeEqualToString("ex.message", message);
     }
 }
 
-testException("undefined.a++", 0, 9, 11, "'undefined' is not an object (evaluating 'undefined.a')");
-testException("++undefined.a", 2, 11, 13, "'undefined' is not an object (evaluating 'undefined.a')");
-testException("undefined[0]++", 0, 9, 12, "'undefined' is not an object (evaluating 'undefined[0]')");
-testException("++undefined[1]", 2, 11, 14, "'undefined' is not an object (evaluating 'undefined[1]')");
-testException("undefined.b", 0, 9, 11, "'undefined' is not an object (evaluating 'undefined.b')");
-testException("undefined[0]", 0, 9, 12, "'undefined' is not an object (evaluating 'undefined[0]')");
-testException("undefined.b += 1", 0, 9, 11, "'undefined' is not an object (evaluating 'undefined.b')");
-testException("undefined[0] += 1", 0, 9, 12, "'undefined' is not an object (evaluating 'undefined[0]')");
-testException("undefined()", 0, 9, 11, "'undefined' is not a function (evaluating 'undefined()')");
-testException("new undefined()", 0, 13, 15, "'undefined' is not a constructor (evaluating 'new undefined()')");
-testException("({}).b()", 0, 6, 8, "'undefined' is not a function (evaluating '({}).b()')");
-testException("new {}.b()", 0, 8, 10, "'undefined' is not a constructor (evaluating 'new {}.b()')");
-testException("1()", 0, 1, 3, "'1' is not a function (evaluating '1()')");
-testException("new 1()", 0, 5, 7, "'1' is not a constructor (evaluating 'new 1()')");
+function func() {}
+
+testException("undefined.a++", 0, 9, 11, "undefined is not an object (evaluating 'undefined.a')");
+testException("++undefined.a", 2, 11, 13, "undefined is not an object (evaluating 'undefined.a')");
+testException("undefined[0]++", 0, 9, 12, "undefined is not an object (evaluating 'undefined[0]')");
+testException("++undefined[1]", 2, 11, 14, "undefined is not an object (evaluating 'undefined[1]')");
+testException("undefined.b", 0, 9, 11, "undefined is not an object (evaluating 'undefined.b')");
+testException("undefined[0]", 0, 9, 12, "undefined is not an object (evaluating 'undefined[0]')");
+testException("undefined.b += 1", 0, 9, 11, "undefined is not an object (evaluating 'undefined.b')");
+testException("undefined[0] += 1", 0, 9, 12, "undefined is not an object (evaluating 'undefined[0]')");
+testException("undefined()", 0, 9, 11, "undefined is not a function. (In 'undefined()', 'undefined' is undefined)");
+testException("new undefined()", 0, 13, 15, "undefined is not a constructor (evaluating 'new undefined()')");
+testException("({}).b()", 0, 6, 8, "({}).b is not a function. (In '({}).b()', '({}).b' is undefined)");
+testException("new {}.b()", 0, 8, 10, "undefined is not a constructor (evaluating 'new {}.b()')");
+testException("1()", 0, 1, 3, "1 is not a function. (In '1()', '1' is 1)");
+testException("new 1()", 0, 5, 7, "1 is not a constructor (evaluating 'new 1()')");
 testException("throw { message : 'thrown object' }", 0, undefined, 35, "thrown object");
-testException("1 in undefined", 0, 5, 14, "'undefined' is not a valid argument for 'in' (evaluating '1 in undefined')");
-testException("1 instanceof undefined", 0, 13, 22, "'undefined' is not a valid argument for 'instanceof' (evaluating '1 instanceof undefined')");
-testException("for (undefined.b in [1]) {}", 5, 14, 16, "'undefined' is not an object (evaluating 'undefined.b')");
-testException("for (undefined[0] in [1]) {}", 5, 14, 17, "'undefined' is not an object (evaluating 'undefined[0]')");
-testException("undefined.a = 5", 0, 9, 15, "'undefined' is not an object (evaluating 'undefined.a = 5')");
-testException("undefined[0] = 5", 0, 9, 16, "'undefined' is not an object (evaluating 'undefined[0] = 5')");
-testException("({b:undefined}).b.a = 5", 0, 17, 23, "'undefined' is not an object (evaluating '({b:undefined}).b.a = 5')");
-testException("({b:undefined}).b[0] = 5", 0, 17, 24, "'undefined' is not an object (evaluating '({b:undefined}).b[0] = 5')");
-testException("undefined.a += 5", 0, 9, 11, "'undefined' is not an object (evaluating 'undefined.a')");
-testException("undefined[0] += 5", 0, 9, 12, "'undefined' is not an object (evaluating 'undefined[0]')");
-testException("({b:undefined}).b.a += 5", 0, 17, 19, "'undefined' is not an object (evaluating '({b:undefined}).b.a')");
-testException("({b:undefined}).b[0] += 5", 0, 17, 20, "'undefined' is not an object (evaluating '({b:undefined}).b[0]')");
+testException("1 in undefined", 0, 5, 14, "undefined is not an Object. (evaluating '1 in undefined')");
+testException("1 instanceof undefined", 0, 13, 22, "Right hand side of instanceof is not an object");
+testException("for (undefined.b in [1]) {}", 5, 14, 16, "undefined is not an object (evaluating 'undefined.b')");
+testException("for (undefined[0] in [1]) {}", 5, 14, 17, "undefined is not an object (evaluating 'undefined[0]')");
+testException("undefined.a = 5", 0, 9, 15, "undefined is not an object (evaluating 'undefined.a = 5')");
+testException("undefined[0] = 5", 0, 9, 16, "undefined is not an object (evaluating 'undefined[0] = 5')");
+testException("({b:undefined}).b.a = 5", 0, 17, 23, "undefined is not an object (evaluating '({b:undefined}).b.a = 5')");
+testException("({b:undefined}).b[0] = 5", 0, 17, 24, "undefined is not an object (evaluating '({b:undefined}).b[0] = 5')");
+testException("undefined.a += 5", 0, 9, 11, "undefined is not an object (evaluating 'undefined.a')");
+testException("undefined[0] += 5", 0, 9, 12, "undefined is not an object (evaluating 'undefined[0]')");
+testException("({b:undefined}).b.a += 5", 0, 17, 19, "undefined is not an object (evaluating '({b:undefined}).b.a')");
+testException("({b:undefined}).b[0] += 5", 0, 17, 20, "undefined is not an object (evaluating '({b:undefined}).b[0]')");
+
+testException("[].a.b.x", 0, 4, 5, "undefined is not an object (evaluating '[].a.b')");
+testException("[]['a']['b'].x", 0, 7, 11, "undefined is not an object (evaluating '[]['a']['b']')");
+testException("[].a['b'].x", 0, 4, 8, "undefined is not an object (evaluating '[].a['b']')");
+testException("[]['a'].b.x", 0, 7, 8, "undefined is not an object (evaluating '[]['a'].b')");
+
+testException("func(undefined.x)", 5, 14, 15, "undefined is not an object (evaluating 'undefined.x')");
+testException("func(null.x)", 5, 9, 10, "null is not an object (evaluating 'null.x')");
+testException("func(undefined[0])", 5, 14, 16, "undefined is not an object (evaluating 'undefined[0]')");
+testException("func(null[0])", 5, 9, 11, "null is not an object (evaluating 'null[0]')");
index 4339912..9daf1f0 100644 (file)
@@ -1,3 +1,17 @@
+2016-10-13  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Exception message for expressions with multiple bracket accesses is inconsistent / incorrect
+        https://bugs.webkit.org/show_bug.cgi?id=163426
+
+        Reviewed by Geoffrey Garen.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::BracketAccessorNode::emitBytecode):
+        It matters where emitExpressionInfo is called since it gathers
+        info about where we are in the instruction stream. We need to
+        emit it before the bytecode that we want to associate the data
+        with. In this case, before the getById / getByVal.
+
 2016-10-13  Mark Lam  <mark.lam@apple.com>
 
         Fix Array.prototype.splice ES6 compliance.
index 5d17a04..d387cdf 100644 (file)
@@ -633,15 +633,17 @@ RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, Regi
         RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
         RefPtr<RegisterID> thisValue = generator.ensureThis();
         RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
+
         if (isNonIndexStringElement(*m_subscript)) {
             const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
+            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
             generator.emitGetById(finalDest.get(), superBase.get(), thisValue.get(), id);
         } else  {
             RefPtr<RegisterID> subscript = generator.emitNode(m_subscript);
+            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
             generator.emitGetByVal(finalDest.get(), superBase.get(), thisValue.get(), subscript.get());
         }
 
-        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
         generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
         return finalDest.get();
     }
@@ -651,15 +653,15 @@ RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, Regi
 
     if (isNonIndexStringElement(*m_subscript)) {
         RefPtr<RegisterID> base = generator.emitNode(m_base);
+        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
         ret = generator.emitGetById(finalDest.get(), base.get(), static_cast<StringNode*>(m_subscript)->value());
     } else {
         RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
         RegisterID* property = generator.emitNode(m_subscript);
+        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
         ret = generator.emitGetByVal(finalDest.get(), base.get(), property);
     }
 
-    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
-
     generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
     return ret;
 }