diff --git a/harness/assert.js b/harness/assert.js index 35abaf8f6ddaf410c43d64f5472567facc6f3c40..9abf3e13cd02ab5b031b96792dda177b31ea0b33 100644 --- a/harness/assert.js +++ b/harness/assert.js @@ -51,24 +51,30 @@ assert.notSameValue = function (actual, unexpected, message) { $ERROR(message); }; -assert.throws = function (expectedErrorConstructor, func) { +assert.throws = function (expectedErrorConstructor, func, message) { if (func === undefined) { $ERROR('assert.throws requires two arguments: the error constructor and a function to run'); return; } + if (message === undefined) { + message = ''; + } else { + message += ' '; + } try { func(); } catch (thrown) { if (typeof thrown !== 'object' || thrown === null) { - $ERROR('Thrown value was not an object!'); - return; - } - if (thrown.constructor !== expectedErrorConstructor) { - $ERROR('Expected a ' + expectedErrorConstructor.name + ' but got a ' + thrown.constructor.name); + message += 'Thrown value was not an object!'; + $ERROR(message); + } else if (thrown.constructor !== expectedErrorConstructor) { + message += 'Expected a ' + expectedErrorConstructor.name + ' but got a ' + thrown.constructor.name; + $ERROR(message); } return; } - $ERROR('Expected a ' + expectedErrorConstructor.name + ' to be thrown but no exception was thrown at all'); + message += 'Expected a ' + expectedErrorConstructor.name + ' to be thrown but no exception was thrown at all'; + $ERROR(message); }; diff --git a/test/built-ins/RegExp/unicode_restricted_brackets.js b/test/built-ins/RegExp/unicode_restricted_brackets.js new file mode 100755 index 0000000000000000000000000000000000000000..a588180519797253b85ce1ec0f78aad53f66831c --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_brackets.js @@ -0,0 +1,19 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExp. + Tested extension: "Atom[U] :: PatternCharacter" +es6id: 21.1.2 +---*/ + +// Single parentheses and brackets. +assert.throws(SyntaxError, function() { RegExp("(", "u"); }); +assert.throws(SyntaxError, function() { RegExp(")", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[", "u"); }); +assert.throws(SyntaxError, function() { RegExp("]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{", "u"); }); +assert.throws(SyntaxError, function() { RegExp("}", "u"); }); diff --git a/test/built-ins/RegExp/unicode_restricted_character_class_escape.js b/test/built-ins/RegExp/unicode_restricted_character_class_escape.js new file mode 100755 index 0000000000000000000000000000000000000000..d2eb4ac8203d697f1b70c341e9f5d607fc7a4817 --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_character_class_escape.js @@ -0,0 +1,37 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExp. + Tested extension: "ClassAtomNoDashInRange :: \ ClassEscape but only if ClassEscape evaluates to a CharSet with exactly one character" +es6id: 21.2.2.15.1 +---*/ + +// Leading CharacterClassEscape. +assert.throws(SyntaxError, function() { RegExp("[\\d-a]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\D-a]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\s-a]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\S-a]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\w-a]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\W-a]", "u"); }); + + +// Trailing CharacterClassEscape. +assert.throws(SyntaxError, function() { RegExp("[a-\\d]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[a-\\D]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[a-\\s]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[a-\\S]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[a-\\w]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[a-\\W]", "u"); }); + + +// Leading and trailing CharacterClassEscape. +assert.throws(SyntaxError, function() { RegExp("[\\d-\\d]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\D-\\D]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\s-\\s]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\S-\\S]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\w-\\w]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\W-\\W]", "u"); }); diff --git a/test/built-ins/RegExp/unicode_restricted_identity_escape.js b/test/built-ins/RegExp/unicode_restricted_identity_escape.js new file mode 100755 index 0000000000000000000000000000000000000000..a53656122ef0cc3ea9d4100aafb776a9f1b58beb --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_identity_escape.js @@ -0,0 +1,65 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExps. + Tested extension: "IdentityEscape[U] :: [~U] SourceCharacter but not c" +es6id: 21.1.2 +---*/ + +function isSyntaxCharacter(c) { + switch (c) { + case "^": + case "$": + case "\\": + case ".": + case "*": + case "+": + case "?": + case "(": + case ")": + case "[": + case "]": + case "{": + case "}": + case "|": + return true; + default: + return false; + } +} + +function isAlphaDigit(c) { + return ("0" <= c && c <= "9") || ("A" <= c && c <= "Z") || ("a" <= c && c <= "z"); +} + + +// IdentityEscape in AtomEscape. +// +// AtomEscape[U] :: CharacterEscape[?U] +// CharacterEscape[U] :: IdentityEscape[?U] +for (var cu = 0x00; cu <= 0x7f; ++cu) { + var s = String.fromCharCode(cu); + if (!isAlphaDigit(s) && !isSyntaxCharacter(s) && s !== "/") { + assert.throws(SyntaxError, function() { + RegExp("\\" + s, "u"); + }, "Invalid IdentityEscape '\\" + s + "'"); + } +} + + +// IdentityEscape in ClassEscape. +// +// ClassEscape[U] :: CharacterEscape[?U] +// CharacterEscape[U] :: IdentityEscape[?U] +for (var cu = 0x00; cu <= 0x7f; ++cu) { + var s = String.fromCharCode(cu); + if (!isAlphaDigit(s) && !isSyntaxCharacter(s) && s !== "/" && s !== "-") { + assert.throws(SyntaxError, function() { + RegExp("[\\" + s + "]", "u"); + }, "Invalid IdentityEscape '\\" + s + "'"); + } +} diff --git a/test/built-ins/RegExp/unicode_restricted_identity_escape_c.js b/test/built-ins/RegExp/unicode_restricted_identity_escape_c.js new file mode 100755 index 0000000000000000000000000000000000000000..74a9239f8a86535d86029bb9ab962045f641125a --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_identity_escape_c.js @@ -0,0 +1,45 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExp. + Tested extension: "IdentityEscape[U] :: [~U] SourceCharacter but not c" +es6id: 21.1.2 +---*/ + +function isAlpha(c) { + return ("A" <= c && c <= "Z") || ("a" <= c && c <= "z"); +} + + +// "c ControlLetter" sequence in AtomEscape. +// +// AtomEscape[U] :: CharacterEscape[?U] +// CharacterEscape[U] :: c ControlLetter +assert.throws(SyntaxError, function() { RegExp("\\c", "u"); }); +for (var cu = 0x00; cu <= 0x7f; ++cu) { + var s = String.fromCharCode(cu); + if (!isAlpha(s)) { + assert.throws(SyntaxError, function() { + RegExp("\\c" + s, "u"); + }, "ControlLetter '" + s + "'"); + } +} + + +// "c ControlLetter" sequence in ClassEscape. +// +// ClassEscape[U] :: CharacterEscape[?U] +// CharacterEscape[U] :: c ControlLetter +assert.throws(SyntaxError, function() { RegExp("[\\c]", "u"); }); +for (var cu = 0x00; cu <= 0x7f; ++cu) { + var s = String.fromCharCode(cu); + if (!isAlpha(s)) { + assert.throws(SyntaxError, function() { + RegExp("[\\c" + s + "]", "u"); + }, "ControlLetter '" + s + "'"); + } +} diff --git a/test/built-ins/RegExp/unicode_restricted_identity_escape_u.js b/test/built-ins/RegExp/unicode_restricted_identity_escape_u.js new file mode 100755 index 0000000000000000000000000000000000000000..4795ab400cfd157e057509579aa6fd21f3d4311f --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_identity_escape_u.js @@ -0,0 +1,40 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExp. + Tested extension: "IdentityEscape[U] :: [~U] SourceCharacter but not c" +es6id: 21.1.2 +---*/ + +// Incomplete RegExpUnicodeEscapeSequence in AtomEscape not parsed as IdentityEscape. +// +// AtomEscape[U] :: CharacterEscape[?U] +// CharacterEscape[U] :: RegExpUnicodeEscapeSequence[?U] +assert.throws(SyntaxError, function() { RegExp("\\u", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\u1", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\u12", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\u123", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\u{", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\u{}", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\u{1", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\u{12", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\u{123", "u"); }); + + +// Incomplete RegExpUnicodeEscapeSequence in ClassEscape not parsed as IdentityEscape. +// +// ClassEscape[U] :: CharacterEscape[?U] +// CharacterEscape[U] :: RegExpUnicodeEscapeSequence[?U] +assert.throws(SyntaxError, function() { RegExp("[\\u]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\u1]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\u12]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\u123]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\u{]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\u{}]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\u{1]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\u{12]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\u{123]", "u"); }); diff --git a/test/built-ins/RegExp/unicode_restricted_identity_escape_x.js b/test/built-ins/RegExp/unicode_restricted_identity_escape_x.js new file mode 100755 index 0000000000000000000000000000000000000000..1b32ac98ce16b4a8914567bfbdd6a89315916f0b --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_identity_escape_x.js @@ -0,0 +1,26 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExp. + Tested extension: "IdentityEscape[U] :: [~U] SourceCharacter but not c" +es6id: 21.1.2 +---*/ + +// Incomplete HexEscapeSequence in AtomEscape not parsed as IdentityEscape. +// +// AtomEscape[U] :: CharacterEscape[?U] +// CharacterEscape[U] :: HexEscapeSequence +assert.throws(SyntaxError, function() { RegExp("\\x", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\x1", "u"); }); + + +// Incomplete HexEscapeSequence in ClassEscape not parsed as IdentityEscape. +// +// ClassEscape[U] :: CharacterEscape[?U] +// CharacterEscape[U] :: HexEscapeSequence +assert.throws(SyntaxError, function() { RegExp("[\\x]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\x1]", "u"); }); diff --git a/test/built-ins/RegExp/unicode_restricted_incomple_quantifier.js b/test/built-ins/RegExp/unicode_restricted_incomple_quantifier.js new file mode 100755 index 0000000000000000000000000000000000000000..a75c3ab3f7a533cd624298184c94817c08175e9b --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_incomple_quantifier.js @@ -0,0 +1,24 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExp. + Tested extension: "Atom[U] :: PatternCharacter" +es6id: 21.1.2 +---*/ + +// Incomplete quantifier with atom. +assert.throws(SyntaxError, function() { RegExp("a{", "u"); }); +assert.throws(SyntaxError, function() { RegExp("a{1", "u"); }); +assert.throws(SyntaxError, function() { RegExp("a{1,", "u"); }); +assert.throws(SyntaxError, function() { RegExp("a{1,2", "u"); }); + + +// Incomplete quantifier without atom. +assert.throws(SyntaxError, function() { RegExp("{", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{1", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{1,", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{1,2", "u"); }); diff --git a/test/built-ins/RegExp/unicode_restricted_octal_escape.js b/test/built-ins/RegExp/unicode_restricted_octal_escape.js new file mode 100755 index 0000000000000000000000000000000000000000..e2b075a244867147f21ebb9bc0e39fe2a0d860cb --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_octal_escape.js @@ -0,0 +1,72 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExp. + Tested extension: "CharacterEscape[U] :: [~U] LegacyOctalEscapeSequence" +es6id: 21.1.2 +---*/ + +// DecimalEscape without leading 0 in AtomEscape. +// +// AtomEscape[U] :: DecimalEscape +// DecimalEscape :: DecimalIntegerLiteral [lookahead /= DecimalDigit] +assert.throws(SyntaxError, function() { RegExp("\\1", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\2", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\3", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\4", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\5", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\6", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\7", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\8", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\9", "u"); }); + + +// DecimalEscape without leading 0 in ClassEscape. +// +// ClassEscape[U] :: DecimalEscape +// DecimalEscape :: DecimalIntegerLiteral [lookahead /= DecimalDigit] +assert.throws(SyntaxError, function() { RegExp("[\\1]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\2]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\3]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\4]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\5]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\6]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\7]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\8]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\9]", "u"); }); + + +// DecimalEscape with leading 0 in AtomEscape. +// +// Atom[U] :: DecimalEscape +// DecimalEscape :: DecimalIntegerLiteral [lookahead /= DecimalDigit] +assert.throws(SyntaxError, function() { RegExp("\\00", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\01", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\02", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\03", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\04", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\05", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\06", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\07", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\08", "u"); }); +assert.throws(SyntaxError, function() { RegExp("\\09", "u"); }); + + +// DecimalEscape with leading 0 in ClassEscape. +// +// ClassEscape[U] :: DecimalEscape +// DecimalEscape :: DecimalIntegerLiteral [lookahead /= DecimalDigit] +assert.throws(SyntaxError, function() { RegExp("[\\00]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\01]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\02]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\03]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\04]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\05]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\06]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\07]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\08]", "u"); }); +assert.throws(SyntaxError, function() { RegExp("[\\09]", "u"); }); diff --git a/test/built-ins/RegExp/unicode_restricted_quantifiable_assertion.js b/test/built-ins/RegExp/unicode_restricted_quantifiable_assertion.js new file mode 100755 index 0000000000000000000000000000000000000000..75530772d7d4b876a34137482338416a10c24927 --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_quantifiable_assertion.js @@ -0,0 +1,46 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExps. + Tested extension: "ExtendedTerm :: QuantifiableAssertion Quantifier" +es6id: 21.1.2 +---*/ + +// Positive lookahead with quantifier. +assert.throws(SyntaxError, function() { RegExp("(?=.)*", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.)+", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.)?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.){1}", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.){1,}", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.){1,2}", "u"); }); + + +// Positive lookahead with reluctant quantifier. +assert.throws(SyntaxError, function() { RegExp("(?=.)*?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.)+?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.)??", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.){1}?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.){1,}?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?=.){1,2}?", "u"); }); + + +// Negative lookahead with quantifier. +assert.throws(SyntaxError, function() { RegExp("(?!.)*", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.)+", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.)?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.){1}", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.){1,}", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.){1,2}", "u"); }); + + +// Negative lookahead with reluctant quantifier. +assert.throws(SyntaxError, function() { RegExp("(?!.)*?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.)+?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.)??", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.){1}?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.){1,}?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("(?!.){1,2}?", "u"); }); diff --git a/test/built-ins/RegExp/unicode_restricted_quantifier_without_atom.js b/test/built-ins/RegExp/unicode_restricted_quantifier_without_atom.js new file mode 100755 index 0000000000000000000000000000000000000000..371cc7181845eda9b9c085dcd84e0c5543da2a53 --- /dev/null +++ b/test/built-ins/RegExp/unicode_restricted_quantifier_without_atom.js @@ -0,0 +1,28 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Extension B.1.4 is not applied for Unicode RegExp +info: > + The compatibility extensions defined in B.1.4 Regular Expressions Patterns + are not applied for Unicode RegExp. + Tested extension: "Atom[U] :: PatternCharacter" +es6id: 21.1.2 +---*/ + +// Quantifier without atom. +assert.throws(SyntaxError, function() { RegExp("*", "u"); }); +assert.throws(SyntaxError, function() { RegExp("+", "u"); }); +assert.throws(SyntaxError, function() { RegExp("?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{1}", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{1,}", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{1,2}", "u"); }); + + +// Reluctant quantifier without atom. +assert.throws(SyntaxError, function() { RegExp("*?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("+?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("??", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{1}?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{1,}?", "u"); }); +assert.throws(SyntaxError, function() { RegExp("{1,2}?", "u"); });