js/src/tests/ecma_5/misc/builtin-methods-reject-null-undefined-this.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/tests/ecma_5/misc/builtin-methods-reject-null-undefined-this.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,153 @@
     1.4 +/*
     1.5 + * Any copyright is dedicated to the Public Domain.
     1.6 + * http://creativecommons.org/licenses/publicdomain/
     1.7 + */
     1.8 +
     1.9 +//-----------------------------------------------------------------------------
    1.10 +var BUGNUMBER = 619283;
    1.11 +var summary =
    1.12 +  "ECMAScript built-in methods that immediately throw when |this| is " +
    1.13 +  "|undefined| or |null| (due to CheckObjectCoercible, ToObject, or ToString)";
    1.14 +
    1.15 +print(BUGNUMBER + ": " + summary);
    1.16 +
    1.17 +/**************
    1.18 + * BEGIN TEST *
    1.19 + **************/
    1.20 +
    1.21 +// We can't just exhaustively loop over everything because 1) method properties
    1.22 +// might be extensions with special |this| handling, and 2) some methods don't
    1.23 +// *quite* immediately throw a TypeError, first thing, if |this| is |undefined|
    1.24 +// or |null|, or their algorithms are very slightly ambiguous about whether they
    1.25 +// do.  Why?  Ipse-dixitism.  *shrug*
    1.26 +
    1.27 +var ClassToMethodMap =
    1.28 +  {
    1.29 +    Object:  [/* "toString" has special |this| handling */
    1.30 +              "toLocaleString", "valueOf", "hasOwnProperty",
    1.31 +              /*
    1.32 +               * "isPrototypeOf" has special |this| handling already tested in
    1.33 +               * ecma_5/Object/isPrototypeOf.js.
    1.34 +               */
    1.35 +              /*
    1.36 +               * "isPrototypeOf" has special |this| handling already tested in
    1.37 +               * ecma_5/Object/propertyIsEnumerable.js.
    1.38 +               */],
    1.39 +    // Function methods often don't ToObject(this) as their very first step,
    1.40 +    // and they're already stepwise well-tested such that manual tests here
    1.41 +    // would be redundant.
    1.42 +    Array:   ["toString", "toLocaleString", "concat", "join", "pop", "push",
    1.43 +              "reverse", "shift", "slice", "sort", "splice", "unshift",
    1.44 +              "indexOf", "lastIndexOf", "every", "some", "forEach", "map",
    1.45 +              "filter", "reduce", "reduceRight"],
    1.46 +    String:  ["toString", "valueOf", "charAt", "charCodeAt", "concat",
    1.47 +              "indexOf", "lastIndexOf", "localeCompare", "match", "replace",
    1.48 +              "search", "slice", "split", "substring", "toLowerCase",
    1.49 +              "toLocaleLowerCase", "toUpperCase", "toLocaleUpperCase", "trim",
    1.50 +              /*
    1.51 +               * "trimLeft" and "trimRight" are non-standard and thus are tested
    1.52 +               * in ecma_5/extensions/trim-extensions.js.
    1.53 +               */
    1.54 +              ],
    1.55 +    Boolean: ["toString", "valueOf"],
    1.56 +    Number:  ["toString", "toLocaleString", "valueOf",
    1.57 +              /*
    1.58 +               * toFixed doesn't *immediately* test |this| for number or
    1.59 +               * Number-ness, but because the ToInteger(void 0) which arguably
    1.60 +               * precedes it in the toFixed algorithm won't throw in this test,
    1.61 +               * we don't need to specially test it.
    1.62 +               */
    1.63 +              "toFixed",
    1.64 +              "toExponential", "toPrecision"],
    1.65 +    Date:    ["toString", "toDateString", "toTimeString", "toLocaleString",
    1.66 +              "toLocaleDateString", "toLocaleTimeString", "valueOf", "getTime",
    1.67 +              "getFullYear", "getUTCFullYear", "getMonth", "getUTCMonth",
    1.68 +              "getDate", "getUTCDate", "getDay", "getUTCDay", "getHours",
    1.69 +              "getUTCHours", "getMinutes", "getUTCMinutes", "getSeconds",
    1.70 +              "getUTCSeconds", "getMilliseconds", "getUTCMilliseconds",
    1.71 +              /*
    1.72 +               * toFixed doesn't *immediately* test |this| for number or
    1.73 +               * Number-ness, but because the TimeClip(ToNumber(void 0)) which
    1.74 +               * arguably precedes it in the setTime algorithm won't throw in
    1.75 +               * this test, we don't need to specially test it.
    1.76 +               */
    1.77 +              "setTime",
    1.78 +              "getTimezoneOffset", "setMilliseconds", "setUTCMilliseconds",
    1.79 +              "setSeconds", "setUTCSeconds", "setMinutes", "setUTCMinutes",
    1.80 +              "setHours", "setUTCHours", "setDate", "setUTCDate",  "setMonth",
    1.81 +              "setUTCMonth", "setFullYear", "setUTCFullYear", "toUTCString",
    1.82 +              "toISOString", "toJSON"],
    1.83 +    RegExp:  ["exec", "test", "toString"],
    1.84 +    Error:   ["toString"],
    1.85 +  };
    1.86 +
    1.87 +var badThisValues = [null, undefined];
    1.88 +
    1.89 +function testMethod(Class, className, method)
    1.90 +{
    1.91 +  var expr;
    1.92 +
    1.93 +  // Try out explicit this values
    1.94 +  for (var i = 0, sz = badThisValues.length; i < sz; i++)
    1.95 +  {
    1.96 +    var badThis = badThisValues[i];
    1.97 +
    1.98 +    expr = className + ".prototype." + method + ".call(" + badThis + ")";
    1.99 +    try
   1.100 +    {
   1.101 +      Class.prototype[method].call(badThis);
   1.102 +      throw new Error(expr + " didn't throw a TypeError");
   1.103 +    }
   1.104 +    catch (e)
   1.105 +    {
   1.106 +      assertEq(e instanceof TypeError, true,
   1.107 +               "wrong error for " + expr + ", instead threw " + e);
   1.108 +    }
   1.109 +
   1.110 +    expr = className + ".prototype." + method + ".apply(" + badThis + ")";
   1.111 +    try
   1.112 +    {
   1.113 +      Class.prototype[method].apply(badThis);
   1.114 +      throw new Error(expr + " didn't throw a TypeError");
   1.115 +    }
   1.116 +    catch (e)
   1.117 +    {
   1.118 +      assertEq(e instanceof TypeError, true,
   1.119 +               "wrong error for " + expr + ", instead threw " + e);
   1.120 +    }
   1.121 +  }
   1.122 +
   1.123 +  // ..and for good measure..
   1.124 +
   1.125 +  expr = "(0, " + className + ".prototype." + method + ")()"
   1.126 +  try
   1.127 +  {
   1.128 +    // comma operator to call GetValue() on the method and de-Reference it
   1.129 +    (0, Class.prototype[method])();
   1.130 +    throw new Error(expr + " didn't throw a TypeError");
   1.131 +  }
   1.132 +  catch (e)
   1.133 +  {
   1.134 +    assertEq(e instanceof TypeError, true,
   1.135 +             "wrong error for " + expr + ", instead threw " + e);
   1.136 +  }
   1.137 +}
   1.138 +
   1.139 +for (var className in ClassToMethodMap)
   1.140 +{
   1.141 +  var Class = this[className];
   1.142 +
   1.143 +  var methodNames = ClassToMethodMap[className];
   1.144 +  for (var i = 0, sz = methodNames.length; i < sz; i++)
   1.145 +  {
   1.146 +    var method = methodNames[i];
   1.147 +    testMethod(Class, className, method);
   1.148 +  }
   1.149 +}
   1.150 +
   1.151 +/******************************************************************************/
   1.152 +
   1.153 +if (typeof reportCompare === "function")
   1.154 +  reportCompare(true, true);
   1.155 +
   1.156 +print("All tests passed!");

mercurial