From cb40133425481e57fb80795111b2db4a81aba863 Mon Sep 17 00:00:00 2001
From: jugglinmike <mike@mikepennisi.com>
Date: Mon, 16 May 2016 13:53:30 -0400
Subject: [PATCH] Add tests for Annex B extns to global object (#624)

Extend tests for the `escape` and `unescape` built-ins to assert their
behavior. Rely on the latest ECMAScript draft, which specifies that
`escape` returns hexadecimal codes in upper case.
---
 test/annexB/built-ins/escape/empty-string.js  | 17 ++++
 test/annexB/built-ins/escape/escape-above.js  | 30 ++++++
 test/annexB/built-ins/escape/escape-below.js  | 54 +++++++++++
 .../built-ins/escape/to-string-err-symbol.js  | 16 ++++
 test/annexB/built-ins/escape/to-string-err.js | 19 ++++
 .../built-ins/escape/to-string-observe.js     | 52 ++++++++++
 test/annexB/built-ins/escape/unmodified.js    | 21 +++++
 .../annexB/built-ins/unescape/empty-string.js | 17 ++++
 .../built-ins/unescape/four-ignore-bad-u.js   | 28 ++++++
 .../built-ins/unescape/four-ignore-end-str.js | 94 +++++++++++++++++++
 .../built-ins/unescape/four-ignore-non-hex.js | 43 +++++++++
 test/annexB/built-ins/unescape/four.js        | 73 ++++++++++++++
 .../unescape/to-string-err-symbol.js          | 16 ++++
 .../built-ins/unescape/to-string-err.js       | 19 ++++
 .../built-ins/unescape/to-string-observe.js   | 52 ++++++++++
 .../built-ins/unescape/two-ignore-end-str.js  | 47 ++++++++++
 .../built-ins/unescape/two-ignore-non-hex.js  | 35 +++++++
 test/annexB/built-ins/unescape/two.js         | 69 ++++++++++++++
 18 files changed, 702 insertions(+)
 create mode 100644 test/annexB/built-ins/escape/empty-string.js
 create mode 100644 test/annexB/built-ins/escape/escape-above.js
 create mode 100644 test/annexB/built-ins/escape/escape-below.js
 create mode 100644 test/annexB/built-ins/escape/to-string-err-symbol.js
 create mode 100644 test/annexB/built-ins/escape/to-string-err.js
 create mode 100644 test/annexB/built-ins/escape/to-string-observe.js
 create mode 100644 test/annexB/built-ins/escape/unmodified.js
 create mode 100644 test/annexB/built-ins/unescape/empty-string.js
 create mode 100644 test/annexB/built-ins/unescape/four-ignore-bad-u.js
 create mode 100644 test/annexB/built-ins/unescape/four-ignore-end-str.js
 create mode 100644 test/annexB/built-ins/unescape/four-ignore-non-hex.js
 create mode 100644 test/annexB/built-ins/unescape/four.js
 create mode 100644 test/annexB/built-ins/unescape/to-string-err-symbol.js
 create mode 100644 test/annexB/built-ins/unescape/to-string-err.js
 create mode 100644 test/annexB/built-ins/unescape/to-string-observe.js
 create mode 100644 test/annexB/built-ins/unescape/two-ignore-end-str.js
 create mode 100644 test/annexB/built-ins/unescape/two-ignore-non-hex.js
 create mode 100644 test/annexB/built-ins/unescape/two.js

diff --git a/test/annexB/built-ins/escape/empty-string.js b/test/annexB/built-ins/escape/empty-string.js
new file mode 100644
index 0000000000..b71660b60b
--- /dev/null
+++ b/test/annexB/built-ins/escape/empty-string.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-escape-string
+es6id: B.2.1.1
+description: Input is the empty string
+info: |
+    1. Let string be ? ToString(string).
+    2. Let length be the number of code units in string.
+    3. Let R be the empty string.
+    4. Let k be 0.
+    5. Repeat, while k < length,
+       [...]
+    6. Return R.
+---*/
+
+assert.sameValue(escape(''), '');
diff --git a/test/annexB/built-ins/escape/escape-above.js b/test/annexB/built-ins/escape/escape-above.js
new file mode 100644
index 0000000000..46a183c9ae
--- /dev/null
+++ b/test/annexB/built-ins/escape/escape-above.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-escape-string
+es6id: B.2.1.1
+description: Escaping of code units above 255
+info: |
+    [...]
+    5. Repeat, while k < length,
+       a. Let char be the code unit (represented as a 16-bit unsigned integer)
+          at index k within string.
+       [...]
+       c. Else if char ≥ 256, then
+          i. Let S be a String containing six code units "%uwxyz" where wxyz
+             are the code units of the four uppercase hexadecimal digits
+             encoding the value of char.
+       [...]
+---*/
+
+assert.sameValue(
+  escape('\u0100\u0101\u0102'), '%u0100%u0101%u0102', '\\u0100\\u0101\\u0102'
+);
+
+assert.sameValue(
+  escape('\ufffd\ufffe\uffff'), '%uFFFD%uFFFE%uFFFF', '\\ufffd\\ufffd\\ufffd'
+);
+
+assert.sameValue(
+  escape('\ud834\udf06'), '%uD834%uDF06', '\\ud834\\udf06 (surrogate pairs)'
+);
diff --git a/test/annexB/built-ins/escape/escape-below.js b/test/annexB/built-ins/escape/escape-below.js
new file mode 100644
index 0000000000..a76a240d39
--- /dev/null
+++ b/test/annexB/built-ins/escape/escape-below.js
@@ -0,0 +1,54 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-escape-string
+es6id: B.2.1.1
+description: Escaping of code units below 255
+info: |
+    [...]
+    5. Repeat, while k < length,
+       a. Let char be the code unit (represented as a 16-bit unsigned integer)
+          at index k within string.
+       [...]
+       d. Else char < 256,
+          i. Let S be a String containing three code units "%xy" where xy are
+             the code units of two uppercase hexadecimal digits encoding the
+             value of char.
+       [...]
+---*/
+
+assert.sameValue(
+  escape('\x00\x01\x02\x03'),
+  '%00%01%02%03',
+  'characters: \\x00\\x01\\x02\\x03'
+);
+
+assert.sameValue(
+  escape('!"#$%&\'()'),
+  '%21%22%23%24%25%26%27%28%29',
+  'characters preceeding "*": !"#$%&\'()'
+);
+
+assert.sameValue(escape(','), '%2C', 'character between "+" and "-": ,');
+
+assert.sameValue(
+  escape(':;<=>?'),
+  '%3A%3B%3C%3D%3E%3F',
+  'characters between "9" and "@": :;<=>?'
+);
+
+assert.sameValue(
+  escape('[\\]^'), '%5B%5C%5D%5E', 'characters between "Z" and "_": [\\]^'
+);
+
+assert.sameValue(escape('`'), '%60', 'character between "_" and "a": `');
+
+assert.sameValue(
+  escape('{|}~\x7f\x80'),
+  '%7B%7C%7D%7E%7F%80',
+  'characters following "z": {|}~\\x7f\\x80'
+);
+
+assert.sameValue(
+  escape('\xfd\xfe\xff'), '%FD%FE%FF', '\\xfd\\xfe\\xff'
+);
diff --git a/test/annexB/built-ins/escape/to-string-err-symbol.js b/test/annexB/built-ins/escape/to-string-err-symbol.js
new file mode 100644
index 0000000000..edce9168fe
--- /dev/null
+++ b/test/annexB/built-ins/escape/to-string-err-symbol.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-escape-string
+es6id: B.2.1.1
+description: Abrupt completion from `ToString` operation (Symbol value)
+info: |
+    1. Let string be ? ToString(string).
+features: [Symbol]
+---*/
+
+var s = Symbol('');
+
+assert.throws(TypeError, function() {
+  escape(s);
+});
diff --git a/test/annexB/built-ins/escape/to-string-err.js b/test/annexB/built-ins/escape/to-string-err.js
new file mode 100644
index 0000000000..4d58272f02
--- /dev/null
+++ b/test/annexB/built-ins/escape/to-string-err.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-escape-string
+es6id: B.2.1.1
+description: Abrupt completion from `ToString` operation
+info: |
+    1. Let string be ? ToString(string).
+---*/
+
+var obj = {
+  toString: function() {
+    throw new Test262Error();
+  }
+};
+
+assert.throws(Test262Error, function() {
+  escape(obj);
+});
diff --git a/test/annexB/built-ins/escape/to-string-observe.js b/test/annexB/built-ins/escape/to-string-observe.js
new file mode 100644
index 0000000000..be0e1bef7a
--- /dev/null
+++ b/test/annexB/built-ins/escape/to-string-observe.js
@@ -0,0 +1,52 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-escape-string
+es6id: B.2.1.1
+description: Observable operations from string coercion
+info: |
+    1. Let string be ? ToString(string).
+---*/
+
+var log, obj;
+
+log = '';
+obj = {
+  toString: function() {
+    log += 'toString';
+  },
+  valueOf: function() {
+    log += 'valueOf';
+  }
+};
+
+escape(obj);
+
+assert.sameValue(log, 'toString');
+
+log = '';
+obj = {
+  toString: null,
+  valueOf: function() {
+    log += 'valueOf';
+  }
+};
+
+escape(obj);
+
+assert.sameValue(log, 'valueOf');
+
+log = '';
+obj = {
+  toString: function() {
+    log += 'toString';
+    return {};
+  },
+  valueOf: function() {
+    log += 'valueOf';
+  }
+};
+
+escape(obj);
+
+assert.sameValue(log, 'toStringvalueOf');
diff --git a/test/annexB/built-ins/escape/unmodified.js b/test/annexB/built-ins/escape/unmodified.js
new file mode 100644
index 0000000000..fbaa33f3b4
--- /dev/null
+++ b/test/annexB/built-ins/escape/unmodified.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-escape-string
+es6id: B.2.1.1
+description: Do not escape a specific set of characters
+info: |
+    [...]
+    5. Repeat, while k < length,
+       a. Let char be the code unit (represented as a 16-bit unsigned integer)
+          at index k within string.
+       b. If char is one of the code units in
+          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_+-./",
+          then
+          i. Let S be a String containing the single code unit char.
+       [...]
+---*/
+
+var passthrough = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_+-./';
+
+assert.sameValue(escape(passthrough), passthrough);
diff --git a/test/annexB/built-ins/unescape/empty-string.js b/test/annexB/built-ins/unescape/empty-string.js
new file mode 100644
index 0000000000..fc7d574d89
--- /dev/null
+++ b/test/annexB/built-ins/unescape/empty-string.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: Input is the empty string
+info: |
+    1. Let string be ? ToString(string).
+    2. Let length be the number of code units in string.
+    3. Let R be the empty string.
+    4. Let k be 0.
+    5. Repeat, while k ≠ length,
+       [...]
+    6. Return R.
+---*/
+
+assert.sameValue(unescape(''), '');
diff --git a/test/annexB/built-ins/unescape/four-ignore-bad-u.js b/test/annexB/built-ins/unescape/four-ignore-bad-u.js
new file mode 100644
index 0000000000..c2801b9973
--- /dev/null
+++ b/test/annexB/built-ins/unescape/four-ignore-bad-u.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: >
+    Does not transform four-character patterns that are not prefixed with the
+    character "u"
+info: |
+    [...]
+    5. Repeat, while k ≠ length,
+       [...]
+       a. Let c be the code unit at index k within string.
+       b. If c is %, then
+          i. If k ≤ length-6 and the code unit at index k+1 within string is u
+             and the four code units at indices k+2, k+3, k+4, and k+5 within
+             string are all hexadecimal digits, then
+             1. Let c be the code unit whose value is the integer represented
+                by the four hexadecimal digits at indices k+2, k+3, k+4, and
+                k+5 within string.
+             2. Increase k by 5.
+       [...]
+---*/
+
+assert.sameValue(unescape('%U0000'), '%U0000');
+assert.sameValue(unescape('%t0000'), '%t0000');
+assert.sameValue(unescape('%v0000'), '%v0000');
+assert.sameValue(unescape('%%0000'), '%\x0000');
diff --git a/test/annexB/built-ins/unescape/four-ignore-end-str.js b/test/annexB/built-ins/unescape/four-ignore-end-str.js
new file mode 100644
index 0000000000..38a588198d
--- /dev/null
+++ b/test/annexB/built-ins/unescape/four-ignore-end-str.js
@@ -0,0 +1,94 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: >
+    Does not transform four-character patterns that are interrupted by the end
+    of the string
+info: |
+    [...]
+    5. Repeat, while k ≠ length,
+       [...]
+       a. Let c be the code unit at index k within string.
+       b. If c is %, then
+          i. If k ≤ length-6 and the code unit at index k+1 within string is u
+             and the four code units at indices k+2, k+3, k+4, and k+5 within
+             string are all hexadecimal digits, then
+             1. Let c be the code unit whose value is the integer represented
+                by the four hexadecimal digits at indices k+2, k+3, k+4, and
+                k+5 within string.
+             2. Increase k by 5.
+       [...]
+---*/
+
+assert.sameValue(unescape('%u'), '%u');
+
+assert.sameValue(unescape('%u0'), '%u0');
+assert.sameValue(unescape('%u1'), '%u1');
+assert.sameValue(unescape('%u2'), '%u2');
+assert.sameValue(unescape('%u3'), '%u3');
+assert.sameValue(unescape('%u4'), '%u4');
+assert.sameValue(unescape('%u5'), '%u5');
+assert.sameValue(unescape('%u6'), '%u6');
+assert.sameValue(unescape('%u7'), '%u7');
+assert.sameValue(unescape('%u8'), '%u8');
+assert.sameValue(unescape('%u9'), '%u9');
+assert.sameValue(unescape('%ua'), '%ua');
+assert.sameValue(unescape('%uA'), '%uA');
+assert.sameValue(unescape('%ub'), '%ub');
+assert.sameValue(unescape('%uB'), '%uB');
+assert.sameValue(unescape('%uc'), '%uc');
+assert.sameValue(unescape('%uC'), '%uC');
+assert.sameValue(unescape('%ud'), '%ud');
+assert.sameValue(unescape('%uD'), '%uD');
+assert.sameValue(unescape('%ue'), '%ue');
+assert.sameValue(unescape('%uE'), '%uE');
+assert.sameValue(unescape('%uf'), '%uf');
+assert.sameValue(unescape('%uF'), '%uF');
+
+assert.sameValue(unescape('%u00'), '%u00');
+assert.sameValue(unescape('%u01'), '%u01');
+assert.sameValue(unescape('%u02'), '%u02');
+assert.sameValue(unescape('%u03'), '%u03');
+assert.sameValue(unescape('%u04'), '%u04');
+assert.sameValue(unescape('%u05'), '%u05');
+assert.sameValue(unescape('%u06'), '%u06');
+assert.sameValue(unescape('%u07'), '%u07');
+assert.sameValue(unescape('%u08'), '%u08');
+assert.sameValue(unescape('%u09'), '%u09');
+assert.sameValue(unescape('%u0a'), '%u0a');
+assert.sameValue(unescape('%u0A'), '%u0A');
+assert.sameValue(unescape('%u0b'), '%u0b');
+assert.sameValue(unescape('%u0B'), '%u0B');
+assert.sameValue(unescape('%u0c'), '%u0c');
+assert.sameValue(unescape('%u0C'), '%u0C');
+assert.sameValue(unescape('%u0d'), '%u0d');
+assert.sameValue(unescape('%u0D'), '%u0D');
+assert.sameValue(unescape('%u0e'), '%u0e');
+assert.sameValue(unescape('%u0E'), '%u0E');
+assert.sameValue(unescape('%u0f'), '%u0f');
+assert.sameValue(unescape('%u0F'), '%u0F');
+
+assert.sameValue(unescape('%u000'), '%u000');
+assert.sameValue(unescape('%u001'), '%u001');
+assert.sameValue(unescape('%u002'), '%u002');
+assert.sameValue(unescape('%u003'), '%u003');
+assert.sameValue(unescape('%u004'), '%u004');
+assert.sameValue(unescape('%u005'), '%u005');
+assert.sameValue(unescape('%u006'), '%u006');
+assert.sameValue(unescape('%u007'), '%u007');
+assert.sameValue(unescape('%u008'), '%u008');
+assert.sameValue(unescape('%u009'), '%u009');
+assert.sameValue(unescape('%u00a'), '%u00a');
+assert.sameValue(unescape('%u00A'), '%u00A');
+assert.sameValue(unescape('%u00b'), '%u00b');
+assert.sameValue(unescape('%u00B'), '%u00B');
+assert.sameValue(unescape('%u00c'), '%u00c');
+assert.sameValue(unescape('%u00C'), '%u00C');
+assert.sameValue(unescape('%u00d'), '%u00d');
+assert.sameValue(unescape('%u00D'), '%u00D');
+assert.sameValue(unescape('%u00e'), '%u00e');
+assert.sameValue(unescape('%u00E'), '%u00E');
+assert.sameValue(unescape('%u00f'), '%u00f');
+assert.sameValue(unescape('%u00F'), '%u00F');
diff --git a/test/annexB/built-ins/unescape/four-ignore-non-hex.js b/test/annexB/built-ins/unescape/four-ignore-non-hex.js
new file mode 100644
index 0000000000..a5ff877d64
--- /dev/null
+++ b/test/annexB/built-ins/unescape/four-ignore-non-hex.js
@@ -0,0 +1,43 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: >
+    Does not transform four-character patterns that contain non-hexadecimal
+    digits
+info: |
+    [...]
+    5. Repeat, while k ≠ length,
+       [...]
+       a. Let c be the code unit at index k within string.
+       b. If c is %, then
+          i. If k ≤ length-6 and the code unit at index k+1 within string is u
+             and the four code units at indices k+2, k+3, k+4, and k+5 within
+             string are all hexadecimal digits, then
+             1. Let c be the code unit whose value is the integer represented
+                by the four hexadecimal digits at indices k+2, k+3, k+4, and
+                k+5 within string.
+             2. Increase k by 5.
+       [...]
+---*/
+
+assert.sameValue(unescape('%u000%0'), '%u000%0');
+
+assert.sameValue(unescape('%u000g0'), '%u000g0');
+assert.sameValue(unescape('%u000G0'), '%u000G0');
+assert.sameValue(unescape('%u00g00'), '%u00g00');
+assert.sameValue(unescape('%u00G00'), '%u00G00');
+assert.sameValue(unescape('%u0g000'), '%u0g000');
+assert.sameValue(unescape('%u0G000'), '%u0G000');
+assert.sameValue(unescape('%ug0000'), '%ug0000');
+assert.sameValue(unescape('%uG0000'), '%uG0000');
+
+assert.sameValue(unescape('%u000u0'), '%u000u0');
+assert.sameValue(unescape('%u000U0'), '%u000U0');
+assert.sameValue(unescape('%u00u00'), '%u00u00');
+assert.sameValue(unescape('%u00U00'), '%u00U00');
+assert.sameValue(unescape('%u0u000'), '%u0u000');
+assert.sameValue(unescape('%u0U000'), '%u0U000');
+assert.sameValue(unescape('%uu0000'), '%uu0000');
+assert.sameValue(unescape('%uU0000'), '%uU0000');
diff --git a/test/annexB/built-ins/unescape/four.js b/test/annexB/built-ins/unescape/four.js
new file mode 100644
index 0000000000..bc0efe9eab
--- /dev/null
+++ b/test/annexB/built-ins/unescape/four.js
@@ -0,0 +1,73 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: Translation of patterns with four digits
+info: |
+    [...]
+    5. Repeat, while k ≠ length,
+       [...]
+       a. Let c be the code unit at index k within string.
+       b. If c is %, then
+          i. If k ≤ length-6 and the code unit at index k+1 within string is u
+             and the four code units at indices k+2, k+3, k+4, and k+5 within
+             string are all hexadecimal digits, then
+             1. Let c be the code unit whose value is the integer represented
+                by the four hexadecimal digits at indices k+2, k+3, k+4, and
+                k+5 within string.
+             2. Increase k by 5.
+       [...]
+---*/
+
+assert.sameValue(unescape('%0%u00000'), '%0\x000', '%u0000');
+assert.sameValue(unescape('%0%u00010'), '%0\x010', '%u0001');
+
+assert.sameValue(unescape('%0%u00290'), '%0)0', '%002900');
+assert.sameValue(unescape('%0%u002a0'), '%0*0', '%002a00');
+assert.sameValue(unescape('%0%u002A0'), '%0*0', '%002A00');
+assert.sameValue(unescape('%0%u002b0'), '%0+0', '%002b00');
+assert.sameValue(unescape('%0%u002B0'), '%0+0', '%002B00');
+assert.sameValue(unescape('%0%u002c0'), '%0,0', '%002c00');
+assert.sameValue(unescape('%0%u002C0'), '%0,0', '%002C00');
+assert.sameValue(unescape('%0%u002d0'), '%0-0', '%002d00');
+assert.sameValue(unescape('%0%u002D0'), '%0-0', '%002D00');
+
+assert.sameValue(unescape('%0%u00390'), '%090', '%003900');
+assert.sameValue(unescape('%0%u003a0'), '%0:0', '%003A00');
+assert.sameValue(unescape('%0%u003A0'), '%0:0', '%003A00');
+
+assert.sameValue(unescape('%0%u003f0'), '%0?0', '%003f00');
+assert.sameValue(unescape('%0%u003F0'), '%0?0', '%003F00');
+assert.sameValue(unescape('%0%u00400'), '%0@0', '%004000');
+
+assert.sameValue(unescape('%0%u005a0'), '%0Z0', '%005a00');
+assert.sameValue(unescape('%0%u005A0'), '%0Z0', '%005A00');
+assert.sameValue(unescape('%0%u005b0'), '%0[0', '%005b00');
+assert.sameValue(unescape('%0%u005B0'), '%0[0', '%005B00');
+
+assert.sameValue(unescape('%0%u005e0'), '%0^0', '%005e00');
+assert.sameValue(unescape('%0%u005E0'), '%0^0', '%005E00');
+assert.sameValue(unescape('%0%u005f0'), '%0_0', '%005f00');
+assert.sameValue(unescape('%0%u005F0'), '%0_0', '%005F00');
+assert.sameValue(unescape('%0%u00600'), '%0`0', '%006000');
+assert.sameValue(unescape('%0%u00610'), '%0a0', '%006100');
+
+assert.sameValue(unescape('%0%u007a0'), '%0z0', '%007a00');
+assert.sameValue(unescape('%0%u007A0'), '%0z0', '%007A00');
+assert.sameValue(unescape('%0%u007b0'), '%0{0', '%007b00');
+assert.sameValue(unescape('%0%u007B0'), '%0{0', '%007B00');
+
+assert.sameValue(unescape('%0%ufffe0'), '%0\ufffe0', '%ufffe');
+assert.sameValue(unescape('%0%uFffe0'), '%0\ufffe0', '%uFffe');
+assert.sameValue(unescape('%0%ufFfe0'), '%0\ufffe0', '%ufFfe');
+assert.sameValue(unescape('%0%uffFe0'), '%0\ufffe0', '%uffFe');
+assert.sameValue(unescape('%0%ufffE0'), '%0\ufffe0', '%ufffE');
+assert.sameValue(unescape('%0%uFFFE0'), '%0\ufffe0', '%uFFFE');
+
+assert.sameValue(unescape('%0%uffff0'), '%0\uffff0', '%uffff');
+assert.sameValue(unescape('%0%uFfff0'), '%0\uffff0', '%uFfff');
+assert.sameValue(unescape('%0%ufFff0'), '%0\uffff0', '%ufFff');
+assert.sameValue(unescape('%0%uffFf0'), '%0\uffff0', '%uffFf');
+assert.sameValue(unescape('%0%ufffF0'), '%0\uffff0', '%ufffF');
+assert.sameValue(unescape('%0%uFFFF0'), '%0\uffff0', '%uFFFF');
diff --git a/test/annexB/built-ins/unescape/to-string-err-symbol.js b/test/annexB/built-ins/unescape/to-string-err-symbol.js
new file mode 100644
index 0000000000..51c9d2c20a
--- /dev/null
+++ b/test/annexB/built-ins/unescape/to-string-err-symbol.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: Abrupt completion from `ToString` operation (Symbol value)
+info: |
+    1. Let string be ? ToString(string).
+features: [Symbol]
+---*/
+
+var s = Symbol('');
+
+assert.throws(TypeError, function() {
+  unescape(s);
+});
diff --git a/test/annexB/built-ins/unescape/to-string-err.js b/test/annexB/built-ins/unescape/to-string-err.js
new file mode 100644
index 0000000000..53698a042d
--- /dev/null
+++ b/test/annexB/built-ins/unescape/to-string-err.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: Abrupt completion from `ToString` operation
+info: |
+    1. Let string be ? ToString(string).
+---*/
+
+var obj = {
+  toString: function() {
+    throw new Test262Error();
+  }
+};
+
+assert.throws(Test262Error, function() {
+  unescape(obj);
+});
diff --git a/test/annexB/built-ins/unescape/to-string-observe.js b/test/annexB/built-ins/unescape/to-string-observe.js
new file mode 100644
index 0000000000..40cde80cae
--- /dev/null
+++ b/test/annexB/built-ins/unescape/to-string-observe.js
@@ -0,0 +1,52 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: Observable operations from string coercion
+info: |
+    1. Let string be ? ToString(string).
+---*/
+
+var log, obj;
+
+log = '';
+obj = {
+  toString: function() {
+    log += 'toString';
+  },
+  valueOf: function() {
+    log += 'valueOf';
+  }
+};
+
+unescape(obj);
+
+assert.sameValue(log, 'toString');
+
+log = '';
+obj = {
+  toString: null,
+  valueOf: function() {
+    log += 'valueOf';
+  }
+};
+
+unescape(obj);
+
+assert.sameValue(log, 'valueOf');
+
+log = '';
+obj = {
+  toString: function() {
+    log += 'toString';
+    return {};
+  },
+  valueOf: function() {
+    log += 'valueOf';
+  }
+};
+
+unescape(obj);
+
+assert.sameValue(log, 'toStringvalueOf');
diff --git a/test/annexB/built-ins/unescape/two-ignore-end-str.js b/test/annexB/built-ins/unescape/two-ignore-end-str.js
new file mode 100644
index 0000000000..83737b62ec
--- /dev/null
+++ b/test/annexB/built-ins/unescape/two-ignore-end-str.js
@@ -0,0 +1,47 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: >
+    Does not transform two-character patterns that are interrupted by the end
+    of the string
+info: |
+    [...]
+    5. Repeat, while k ≠ length,
+       [...]
+       a. Let c be the code unit at index k within string.
+       b. If c is %, then
+          [...]
+          ii. Else if k ≤ length-3 and the two code units at indices k+1 and
+              k+2 within string are both hexadecimal digits, then
+              1. Let c be the code unit whose value is the integer represented
+                 by two zeroes plus the two hexadecimal digits at indices k+1
+                 and k+2 within string.
+              2. Increase k by 2.
+       [...]
+---*/
+
+assert.sameValue(unescape('%'), '%');
+assert.sameValue(unescape('%0'), '%0');
+assert.sameValue(unescape('%1'), '%1');
+assert.sameValue(unescape('%2'), '%2');
+assert.sameValue(unescape('%3'), '%3');
+assert.sameValue(unescape('%4'), '%4');
+assert.sameValue(unescape('%5'), '%5');
+assert.sameValue(unescape('%6'), '%6');
+assert.sameValue(unescape('%7'), '%7');
+assert.sameValue(unescape('%8'), '%8');
+assert.sameValue(unescape('%9'), '%9');
+assert.sameValue(unescape('%a'), '%a');
+assert.sameValue(unescape('%A'), '%A');
+assert.sameValue(unescape('%b'), '%b');
+assert.sameValue(unescape('%B'), '%B');
+assert.sameValue(unescape('%c'), '%c');
+assert.sameValue(unescape('%C'), '%C');
+assert.sameValue(unescape('%d'), '%d');
+assert.sameValue(unescape('%D'), '%D');
+assert.sameValue(unescape('%e'), '%e');
+assert.sameValue(unescape('%E'), '%E');
+assert.sameValue(unescape('%f'), '%f');
+assert.sameValue(unescape('%F'), '%F');
diff --git a/test/annexB/built-ins/unescape/two-ignore-non-hex.js b/test/annexB/built-ins/unescape/two-ignore-non-hex.js
new file mode 100644
index 0000000000..d4cf0999cf
--- /dev/null
+++ b/test/annexB/built-ins/unescape/two-ignore-non-hex.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: >
+    Does not transform two-character patterns that contain non-hexadecimal
+    digits
+info: |
+    [...]
+    5. Repeat, while k ≠ length,
+       [...]
+       a. Let c be the code unit at index k within string.
+       b. If c is %, then
+          [...]
+          ii. Else if k ≤ length-3 and the two code units at indices k+1 and
+              k+2 within string are both hexadecimal digits, then
+              1. Let c be the code unit whose value is the integer represented
+                 by two zeroes plus the two hexadecimal digits at indices k+1
+                 and k+2 within string.
+              2. Increase k by 2.
+       [...]
+---*/
+
+assert.sameValue(unescape('%0%0'), '%0%0');
+
+assert.sameValue(unescape('%0g0'), '%0g0');
+assert.sameValue(unescape('%0G0'), '%0G0');
+assert.sameValue(unescape('%g00'), '%g00');
+assert.sameValue(unescape('%G00'), '%G00');
+
+assert.sameValue(unescape('%0u0'), '%0u0');
+assert.sameValue(unescape('%0U0'), '%0U0');
+assert.sameValue(unescape('%u00'), '%u00');
+assert.sameValue(unescape('%U00'), '%U00');
diff --git a/test/annexB/built-ins/unescape/two.js b/test/annexB/built-ins/unescape/two.js
new file mode 100644
index 0000000000..eea1b4328d
--- /dev/null
+++ b/test/annexB/built-ins/unescape/two.js
@@ -0,0 +1,69 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unescape-string
+es6id: B.2.1.2
+description: Translation of patterns with two digits
+info: |
+    [...]
+    5. Repeat, while k ≠ length,
+       [...]
+       a. Let c be the code unit at index k within string.
+       b. If c is %, then
+          [...]
+          ii. Else if k ≤ length-3 and the two code units at indices k+1 and
+              k+2 within string are both hexadecimal digits, then
+              1. Let c be the code unit whose value is the integer represented
+                 by two zeroes plus the two hexadecimal digits at indices k+1
+                 and k+2 within string.
+              2. Increase k by 2.
+       [...]
+---*/
+
+assert.sameValue(unescape('%0%0000'), '%0\x0000', '%00');
+assert.sameValue(unescape('%0%0100'), '%0\x0100', '%01');
+
+assert.sameValue(unescape('%0%2900'), '%0)00', '%29');
+assert.sameValue(unescape('%0%2a00'), '%0*00', '%2a');
+assert.sameValue(unescape('%0%2A00'), '%0*00', '%2A');
+assert.sameValue(unescape('%0%2b00'), '%0+00', '%2b');
+assert.sameValue(unescape('%0%2B00'), '%0+00', '%2B');
+assert.sameValue(unescape('%0%2c00'), '%0,00', '%2c');
+assert.sameValue(unescape('%0%2C00'), '%0,00', '%2C');
+assert.sameValue(unescape('%0%2d00'), '%0-00', '%2d');
+assert.sameValue(unescape('%0%2D00'), '%0-00', '%2D');
+
+assert.sameValue(unescape('%0%3900'), '%0900', '%39');
+assert.sameValue(unescape('%0%3a00'), '%0:00', '%3A');
+assert.sameValue(unescape('%0%3A00'), '%0:00', '%3A');
+
+assert.sameValue(unescape('%0%3f00'), '%0?00', '%3f');
+assert.sameValue(unescape('%0%3F00'), '%0?00', '%3F');
+assert.sameValue(unescape('%0%4000'), '%0@00', '%40');
+
+assert.sameValue(unescape('%0%5a00'), '%0Z00', '%5a');
+assert.sameValue(unescape('%0%5A00'), '%0Z00', '%5A');
+assert.sameValue(unescape('%0%5b00'), '%0[00', '%5b');
+assert.sameValue(unescape('%0%5B00'), '%0[00', '%5B');
+
+assert.sameValue(unescape('%0%5e00'), '%0^00', '%5e');
+assert.sameValue(unescape('%0%5E00'), '%0^00', '%5E');
+assert.sameValue(unescape('%0%5f00'), '%0_00', '%5f');
+assert.sameValue(unescape('%0%5F00'), '%0_00', '%5F');
+assert.sameValue(unescape('%0%6000'), '%0`00', '%60');
+assert.sameValue(unescape('%0%6100'), '%0a00', '%61');
+
+assert.sameValue(unescape('%0%7a00'), '%0z00', '%7a');
+assert.sameValue(unescape('%0%7A00'), '%0z00', '%7A');
+assert.sameValue(unescape('%0%7b00'), '%0{00', '%7b');
+assert.sameValue(unescape('%0%7B00'), '%0{00', '%7B');
+
+assert.sameValue(unescape('%0%fe00'), '%0\xfe00', '%fe');
+assert.sameValue(unescape('%0%Fe00'), '%0\xfe00', '%Fe');
+assert.sameValue(unescape('%0%fE00'), '%0\xfe00', '%fE');
+assert.sameValue(unescape('%0%FE00'), '%0\xfe00', '%FE');
+
+assert.sameValue(unescape('%0%ff00'), '%0\xff00', '%ff');
+assert.sameValue(unescape('%0%Ff00'), '%0\xff00', '%Ff');
+assert.sameValue(unescape('%0%fF00'), '%0\xff00', '%fF');
+assert.sameValue(unescape('%0%FF00'), '%0\xff00', '%FF');
-- 
GitLab