Changeset 199545 in webkit


Ignore:
Timestamp:
Apr 14, 2016 11:16:35 AM (8 years ago)
Author:
mark.lam@apple.com
Message:

Update treatment of invoking RegExp.prototype methods on RegExp.prototype.
https://bugs.webkit.org/show_bug.cgi?id=155922

Reviewed by Keith Miller.

Source/JavaScriptCore:

According to the TC39 committee, when invoking the following RegExp.prototype
methods on the RegExp.prototype:

  1. RegExp.prototype.flags yields ""
  2. RegExp.prototype.global yields undefined
  3. RegExp.prototype.ignoreCase yields undefined
  4. RegExp.prototype.multiline yields undefined
  5. RegExp.prototype.unicode yields undefined
  6. RegExp.prototype.source yields "(?:)"
  7. RegExp.prototype.sticky yields undefined
  8. RegExp.prototype.toString() yields "/(?:)/"

and RegExp.prototype is still NOT an instance of RegExp. The above behavior
changes is a special dispensation applicable only to RegExp.prototype. The ES6
spec of throwing errors still applies if those methods are applied to anything =
else that is not a RegExp object.

  • runtime/RegExpPrototype.cpp:

(JSC::regExpProtoGetterGlobal):
(JSC::regExpProtoGetterIgnoreCase):
(JSC::regExpProtoGetterMultiline):
(JSC::regExpProtoGetterSticky):
(JSC::regExpProtoGetterUnicode):
(JSC::regExpProtoGetterFlags):
(JSC::regExpProtoGetterSource):

  • Implemented new behavior.
  • tests/es6/miscellaneous_built-in_prototypes_are_not_instances.js:

(test):

  • Updated to match current kangax test.

LayoutTests:

  • fast/regex/script-tests/toString.js:
  • fast/regex/toString-expected.txt:
  • ietestcenter/Javascript/15.10.7.1-1-expected.txt:
  • ietestcenter/Javascript/TestCases/15.10.7.1-1.js:

(ES5Harness.registerTest.test):

  • js/kde/RegExp-expected.txt:
  • js/kde/script-tests/RegExp.js:
  • js/pic/cached-named-property-getter.html:
  • js/regexp-flags-expected.txt:
  • js/script-tests/regexp-flags.js:
  • updated test behaviors in some cases, and rebased results as needed.
  • js/regress/regexp-prototype-is-not-instance-expected.txt: Added.
  • js/regress/regexp-prototype-is-not-instance.html: Added.
  • js/regress/script-tests/regexp-prototype-is-not-instance.js: Added.
  • Tests new RegExp.prototype method behaviors.
Location:
trunk
Files:
3 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r199544 r199545  
     12016-04-14  Mark Lam  <mark.lam@apple.com>
     2
     3        Update treatment of invoking RegExp.prototype methods on RegExp.prototype.
     4        https://bugs.webkit.org/show_bug.cgi?id=155922
     5
     6        Reviewed by Keith Miller.
     7
     8        * fast/regex/script-tests/toString.js:
     9        * fast/regex/toString-expected.txt:
     10        * ietestcenter/Javascript/15.10.7.1-1-expected.txt:
     11        * ietestcenter/Javascript/TestCases/15.10.7.1-1.js:
     12        (ES5Harness.registerTest.test):
     13        * js/kde/RegExp-expected.txt:
     14        * js/kde/script-tests/RegExp.js:
     15        * js/pic/cached-named-property-getter.html:
     16        * js/regexp-flags-expected.txt:
     17        * js/script-tests/regexp-flags.js:
     18        - updated test behaviors in some cases, and rebased results as needed.
     19
     20        * js/regress/regexp-prototype-is-not-instance-expected.txt: Added.
     21        * js/regress/regexp-prototype-is-not-instance.html: Added.
     22        * js/regress/script-tests/regexp-prototype-is-not-instance.js: Added.
     23        - Tests new RegExp.prototype method behaviors.
     24
     25
    1262016-04-14  Frederic Wang  <fwang@igalia.com>
    227
  • trunk/LayoutTests/fast/regex/script-tests/toString.js

    r198447 r199545  
    2020shouldBe("RegExp('/').source", '"\\\\/"');
    2121shouldBe("RegExp('').source", '"(?:)"');
    22 shouldThrow("RegExp.prototype.source", '"TypeError: Type error"');
     22shouldBe("RegExp.prototype.source", '"(?:)"');
    2323
    2424shouldBe("RegExp('/').toString()", '"/\\\\//"');
    2525shouldBe("RegExp('').toString()", '"/(?:)/"');
    26 shouldThrow("RegExp.prototype.toString()", '"TypeError: Type error"');
     26shouldBe("RegExp.prototype.toString()", '"/(?:)/"');
    2727
    2828// These strings are equivalent, since the '\' is identity escaping the '/' at the string level.
  • trunk/LayoutTests/fast/regex/toString-expected.txt

    r198447 r199545  
    66PASS RegExp('/').source is "\\/"
    77PASS RegExp('').source is "(?:)"
    8 PASS RegExp.prototype.source threw exception TypeError: Type error.
     8PASS RegExp.prototype.source is "(?:)"
    99PASS RegExp('/').toString() is "/\\//"
    1010PASS RegExp('').toString() is "/(?:)/"
    11 PASS RegExp.prototype.toString() threw exception TypeError: Type error.
     11PASS RegExp.prototype.toString() is "/(?:)/"
    1212PASS testForwardSlash("^/$", "/"); is true
    1313PASS testForwardSlash("^/$", "/"); is true
  • trunk/LayoutTests/ietestcenter/Javascript/15.10.7.1-1-expected.txt

    r198447 r199545  
    1 15.10.7.1-1 (TestCases/chapter15/15.10/15.10.7/15.10.7.1/15.10.7.1-1.js) RegExp.prototype.source should throw because RegExp.prototype is not a RegExp
     115.10.7.1-1 (TestCases/chapter15/15.10/15.10.7/15.10.7.1/15.10.7.1-1.js) RegExp.prototype.source should be '(?:)'
    22
    33On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
  • trunk/LayoutTests/ietestcenter/Javascript/TestCases/15.10.7.1-1.js

    r198447 r199545  
    2525path: "TestCases/chapter15/15.10/15.10.7/15.10.7.1/15.10.7.1-1.js",
    2626
    27 description: "RegExp.prototype.source should throw because RegExp.prototype is not a RegExp",
     27description: "RegExp.prototype.source should be '(?:)'",
    2828
    2929test: function testcase() {
    30     try {
    31         RegExp.prototype.source;
    32         return false;
    33     } catch (e) {
    34         return true;
    35     }
     30    return RegExp.prototype.source === '(?:)';
    3631 }
    3732});
  • trunk/LayoutTests/js/kde/RegExp-expected.txt

    r198447 r199545  
    9292PASS 'abc'.match(/\u0062/).toString() is 'b'
    9393PASS Object.prototype.toString.apply(RegExp.prototype) is '[object Object]'
    94 PASS RegExp.prototype.toString() threw exception TypeError: Type error.
     94PASS RegExp.prototype.toString() is '/(?:)/'
    9595PASS new RegExp().toString() is '/(?:)/'
    9696PASS (new RegExp('(?:)')).source is '(?:)'
  • trunk/LayoutTests/js/kde/script-tests/RegExp.js

    r198447 r199545  
    148148// not sure what this should return. most importantly
    149149// it doesn't throw an exception
    150 shouldThrow("RegExp.prototype.toString()", "'TypeError: Type error'");
     150shouldBe("RegExp.prototype.toString()", "'/(?:)/'");
    151151
    152152// Empty regular expressions have string representation /(?:)/
  • trunk/LayoutTests/js/pic/cached-named-property-getter.html

    r198698 r199545  
    9393    shouldThrow(function () {
    9494        testCustomGetter({__proto__: r});
    95     }, "TypeError: Type error");
     95    }, "TypeError: The RegExp.prototype.source getter can only be called on a RegExp object");
    9696    shouldThrow(function () {
    9797        testCustomGetter({__proto__: {__proto__: r}});
    98     }, "TypeError: Type error");
     98    }, "TypeError: The RegExp.prototype.source getter can only be called on a RegExp object");
    9999})();
    100100</script>
  • trunk/LayoutTests/js/regexp-flags-expected.txt

    r197869 r199545  
    1515PASS flags.call(/a/ig) is 'gi'
    1616non-object receivers
    17 PASS flags.call(undefined) threw exception TypeError: Type error.
    18 PASS flags.call(null) threw exception TypeError: Type error.
    19 PASS flags.call(false) threw exception TypeError: Type error.
    20 PASS flags.call(true) threw exception TypeError: Type error.
     17PASS flags.call(undefined) threw exception TypeError: The RegExp.prototype.flags getter can only be called on an object.
     18PASS flags.call(null) threw exception TypeError: The RegExp.prototype.flags getter can only be called on an object.
     19PASS flags.call(false) threw exception TypeError: The RegExp.prototype.flags getter can only be called on an object.
     20PASS flags.call(true) threw exception TypeError: The RegExp.prototype.flags getter can only be called on an object.
    2121non-regex objects
    2222PASS flags.call({}) is ''
  • trunk/LayoutTests/js/script-tests/regexp-flags.js

    r197869 r199545  
    1717
    1818debug("non-object receivers");
    19 shouldThrow("flags.call(undefined)", "'TypeError: Type error'");
    20 shouldThrow("flags.call(null)", "'TypeError: Type error'");
    21 shouldThrow("flags.call(false)", "'TypeError: Type error'");
    22 shouldThrow("flags.call(true)", "'TypeError: Type error'");
     19shouldThrow("flags.call(undefined)", "'TypeError: The RegExp.prototype.flags getter can only be called on an object'");
     20shouldThrow("flags.call(null)", "'TypeError: The RegExp.prototype.flags getter can only be called on an object'");
     21shouldThrow("flags.call(false)", "'TypeError: The RegExp.prototype.flags getter can only be called on an object'");
     22shouldThrow("flags.call(true)", "'TypeError: The RegExp.prototype.flags getter can only be called on an object'");
    2323
    2424debug("non-regex objects");
  • trunk/Source/JavaScriptCore/ChangeLog

    r199543 r199545  
     12016-04-14  Mark Lam  <mark.lam@apple.com>
     2
     3        Update treatment of invoking RegExp.prototype methods on RegExp.prototype.
     4        https://bugs.webkit.org/show_bug.cgi?id=155922
     5
     6        Reviewed by Keith Miller.
     7
     8        According to the TC39 committee, when invoking the following RegExp.prototype
     9        methods on the RegExp.prototype:
     10        1. RegExp.prototype.flags yields ""
     11        2. RegExp.prototype.global yields undefined
     12        3. RegExp.prototype.ignoreCase yields undefined
     13        4. RegExp.prototype.multiline yields undefined
     14        5. RegExp.prototype.unicode yields undefined
     15        6. RegExp.prototype.source yields "(?:)"
     16        7. RegExp.prototype.sticky yields undefined
     17        8. RegExp.prototype.toString() yields "/(?:)/"
     18
     19        and RegExp.prototype is still NOT an instance of RegExp.  The above behavior
     20        changes is a special dispensation applicable only to RegExp.prototype.  The ES6
     21        spec of throwing errors still applies if those methods are applied to anything =
     22        else that is not a RegExp object.
     23
     24        * runtime/RegExpPrototype.cpp:
     25        (JSC::regExpProtoGetterGlobal):
     26        (JSC::regExpProtoGetterIgnoreCase):
     27        (JSC::regExpProtoGetterMultiline):
     28        (JSC::regExpProtoGetterSticky):
     29        (JSC::regExpProtoGetterUnicode):
     30        (JSC::regExpProtoGetterFlags):
     31        (JSC::regExpProtoGetterSource):
     32        - Implemented new behavior.
     33
     34        * tests/es6/miscellaneous_built-in_prototypes_are_not_instances.js:
     35        (test):
     36        - Updated to match current kangax test.
     37
    1382016-04-14  Geoffrey Garen  <ggaren@apple.com>
    239
  • trunk/Source/JavaScriptCore/runtime/RegExpPrototype.cpp

    r199514 r199545  
    245245{
    246246    JSValue thisValue = exec->thisValue();
    247     if (!thisValue.inherits(RegExpObject::info()))
    248         return JSValue::encode(jsUndefined());
     247    if (UNLIKELY(!thisValue.inherits(RegExpObject::info()))) {
     248        if (thisValue.inherits(RegExpPrototype::info()))
     249            return JSValue::encode(jsUndefined());
     250        return throwVMTypeError(exec, ASCIILiteral("The RegExp.prototype.global getter can only be called on a RegExp object"));
     251    }
    249252
    250253    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->global()));
     
    254257{
    255258    JSValue thisValue = exec->thisValue();
    256     if (!thisValue.inherits(RegExpObject::info()))
    257         return JSValue::encode(jsUndefined());
     259    if (UNLIKELY(!thisValue.inherits(RegExpObject::info()))) {
     260        if (thisValue.inherits(RegExpPrototype::info()))
     261            return JSValue::encode(jsUndefined());
     262        return throwVMTypeError(exec, ASCIILiteral("The RegExp.prototype.ignoreCase getter can only be called on a RegExp object"));
     263    }
    258264
    259265    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->ignoreCase()));
     
    263269{
    264270    JSValue thisValue = exec->thisValue();
    265     if (!thisValue.inherits(RegExpObject::info()))
    266         return JSValue::encode(jsUndefined());
     271    if (UNLIKELY(!thisValue.inherits(RegExpObject::info()))) {
     272        if (thisValue.inherits(RegExpPrototype::info()))
     273            return JSValue::encode(jsUndefined());
     274        return throwVMTypeError(exec, ASCIILiteral("The RegExp.prototype.multiline getter can only be called on a RegExp object"));
     275    }
    267276
    268277    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->multiline()));
     
    272281{
    273282    JSValue thisValue = exec->thisValue();
    274     if (!thisValue.inherits(RegExpObject::info()))
    275         return JSValue::encode(jsUndefined());
     283    if (UNLIKELY(!thisValue.inherits(RegExpObject::info()))) {
     284        if (thisValue.inherits(RegExpPrototype::info()))
     285            return JSValue::encode(jsUndefined());
     286        return throwVMTypeError(exec, ASCIILiteral("The RegExp.prototype.sticky getter can only be called on a RegExp object"));
     287    }
    276288   
    277289    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->sticky()));
     
    281293{
    282294    JSValue thisValue = exec->thisValue();
    283     if (!thisValue.inherits(RegExpObject::info()))
    284         return JSValue::encode(jsUndefined());
     295    if (UNLIKELY(!thisValue.inherits(RegExpObject::info()))) {
     296        if (thisValue.inherits(RegExpPrototype::info()))
     297            return JSValue::encode(jsUndefined());
     298        return throwVMTypeError(exec, ASCIILiteral("The RegExp.prototype.unicode getter can only be called on a RegExp object"));
     299    }
    285300   
    286301    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->unicode()));
     
    290305{
    291306    JSValue thisValue = exec->thisValue();
    292     if (!thisValue.isObject())
    293         return throwVMTypeError(exec);
     307    if (UNLIKELY(!thisValue.isObject()))
     308        return throwVMTypeError(exec, ASCIILiteral("The RegExp.prototype.flags getter can only be called on an object"));
    294309
    295310    auto flags = flagsString(exec, asObject(thisValue));
     
    409424{
    410425    JSValue thisValue = exec->thisValue();
    411     if (!thisValue.inherits(RegExpObject::info()))
    412         return throwVMTypeError(exec);
     426    if (UNLIKELY(!thisValue.inherits(RegExpObject::info()))) {
     427        if (thisValue.inherits(RegExpPrototype::info()))
     428            return JSValue::encode(jsString(exec, ASCIILiteral("(?:)")));
     429        return throwVMTypeError(exec, ASCIILiteral("The RegExp.prototype.source getter can only be called on a RegExp object"));
     430    }
    413431
    414432    String pattern = asRegExpObject(thisValue)->regExp()->pattern();
  • trunk/Source/JavaScriptCore/tests/es6/miscellaneous_built-in_prototypes_are_not_instances.js

    r198469 r199545  
    22
    33try {
    4   RegExp.prototype.source; return false;
     4  RegExp.prototype.exec(); return false;
    55} catch(e) {}
    66try {
Note: See TracChangeset for help on using the changeset viewer.