js/src/tests/ecma_3/Function/regress-58274.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/tests/ecma_3/Function/regress-58274.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,192 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/*
    1.10 + *
    1.11 + * Date:    15 July 2002
    1.12 + * SUMMARY: Testing functions with double-byte names
    1.13 + * See http://bugzilla.mozilla.org/show_bug.cgi?id=58274
    1.14 + *
    1.15 + * Here is a sample of the problem:
    1.16 + *
    1.17 + *    js> function f\u02B1 () {}
    1.18 + *
    1.19 + *    js> f\u02B1.toSource();
    1.20 + *    function f¦() {}
    1.21 + *
    1.22 + *    js> f\u02B1.toSource().toSource();
    1.23 + *    (new String("function f\xB1() {}"))
    1.24 + *
    1.25 + *
    1.26 + * See how the high-byte information (the 02) has been lost?
    1.27 + * The same thing was happening with the toString() method:
    1.28 + *
    1.29 + *    js> f\u02B1.toString();
    1.30 + *
    1.31 + *    function f¦() {
    1.32 + *    }
    1.33 + *
    1.34 + *    js> f\u02B1.toString().toSource();
    1.35 + *    (new String("\nfunction f\xB1() {\n}\n"))
    1.36 + *
    1.37 + */
    1.38 +//-----------------------------------------------------------------------------
    1.39 +var UBound = 0;
    1.40 +var BUGNUMBER = 58274;
    1.41 +var summary = 'Testing functions with double-byte names';
    1.42 +var ERR = 'UNEXPECTED ERROR! \n';
    1.43 +var ERR_MALFORMED_NAME = ERR + 'Could not find function name in: \n\n';
    1.44 +var status = '';
    1.45 +var statusitems = [];
    1.46 +var actual = '';
    1.47 +var actualvalues = [];
    1.48 +var expect= '';
    1.49 +var expectedvalues = [];
    1.50 +var sEval;
    1.51 +var sName;
    1.52 +
    1.53 +
    1.54 +sEval = "function f\u02B2() {return 42;}";
    1.55 +eval(sEval);
    1.56 +sName = getFunctionName(f\u02B2);
    1.57 +
    1.58 +// Test function call -
    1.59 +status = inSection(1);
    1.60 +actual = f\u02B2();
    1.61 +expect = 42;
    1.62 +addThis();
    1.63 +
    1.64 +// Test both characters of function name -
    1.65 +status = inSection(2);
    1.66 +actual = sName[0];
    1.67 +expect = sEval[9];
    1.68 +addThis();
    1.69 +
    1.70 +status = inSection(3);
    1.71 +actual = sName[1];
    1.72 +expect = sEval[10];
    1.73 +addThis();
    1.74 +
    1.75 +
    1.76 +
    1.77 +sEval = "function f\u02B2\u0AAA () {return 84;}";
    1.78 +eval(sEval);
    1.79 +sName = getFunctionName(f\u02B2\u0AAA);
    1.80 +
    1.81 +// Test function call -
    1.82 +status = inSection(4);
    1.83 +actual = f\u02B2\u0AAA();
    1.84 +expect = 84;
    1.85 +addThis();
    1.86 +
    1.87 +// Test all three characters of function name -
    1.88 +status = inSection(5);
    1.89 +actual = sName[0];
    1.90 +expect = sEval[9];
    1.91 +addThis();
    1.92 +
    1.93 +status = inSection(6);
    1.94 +actual = sName[1];
    1.95 +expect = sEval[10];
    1.96 +addThis();
    1.97 +
    1.98 +status = inSection(7);
    1.99 +actual = sName[2];
   1.100 +expect = sEval[11];
   1.101 +addThis();
   1.102 +
   1.103 +
   1.104 +
   1.105 +
   1.106 +//-----------------------------------------------------------------------------
   1.107 +test();
   1.108 +//-----------------------------------------------------------------------------
   1.109 +
   1.110 +
   1.111 +
   1.112 +/*
   1.113 + * Goal: test that f.toString() contains the proper function name.
   1.114 + *
   1.115 + * Note, however, f.toString() is implementation-independent. For example,
   1.116 + * it may begin with '\nfunction' instead of 'function'. Therefore we use
   1.117 + * a regexp to make sure we extract the name properly.
   1.118 + *
   1.119 + * Here we assume that f has been defined by means of a function statement,
   1.120 + * and not a function expression (where it wouldn't have to have a name).
   1.121 + *
   1.122 + * Rhino uses a Unicode representation for f.toString(); whereas
   1.123 + * SpiderMonkey uses an ASCII representation, putting escape sequences
   1.124 + * for non-ASCII characters. For example, if a function is called f\u02B1,
   1.125 + * then in Rhino the toString() method will present a 2-character Unicode
   1.126 + * string for its name, whereas SpiderMonkey will present a 7-character
   1.127 + * ASCII string for its name: the string literal 'f\u02B1'.
   1.128 + *
   1.129 + * So we force the lexer to condense the string before using it.
   1.130 + * This will give uniform results in Rhino and SpiderMonkey.
   1.131 + */
   1.132 +function getFunctionName(f)
   1.133 +{
   1.134 +  var s = condenseStr(f.toString());
   1.135 +  var re = /\s*function\s+(\S+)\s*\(/;
   1.136 +    var arr = s.match(re);
   1.137 +
   1.138 +  if (!(arr && arr[1]))
   1.139 +    return ERR_MALFORMED_NAME + s;
   1.140 +  return arr[1];
   1.141 +}
   1.142 +
   1.143 +
   1.144 +/*
   1.145 + * This function is the opposite of functions like escape(), which take
   1.146 + * Unicode characters and return escape sequences for them. Here, we force
   1.147 + * the lexer to turn escape sequences back into single characters.
   1.148 + *
   1.149 + * Note we can't simply do |eval(str)|, since in practice |str| will be an
   1.150 + * identifier somewhere in the program (e.g. a function name); thus |eval(str)|
   1.151 + * would return the object that the identifier represents: not what we want.
   1.152 + *
   1.153 + * So we surround |str| lexicographically with quotes to force the lexer to
   1.154 + * evaluate it as a string. Have to strip out any linefeeds first, however -
   1.155 + */
   1.156 +function condenseStr(str)
   1.157 +{
   1.158 +  /*
   1.159 +   * You won't be able to do the next step if |str| has
   1.160 +   * any carriage returns or linefeeds in it. For example:
   1.161 +   *
   1.162 +   *  js> eval("'" + '\nHello' + "'");
   1.163 +   *  1: SyntaxError: unterminated string literal:
   1.164 +   *  1: '
   1.165 +   *  1: ^
   1.166 +   *
   1.167 +   * So replace them with the empty string -
   1.168 +   */
   1.169 +  str = str.replace(/[\r\n]/g, '')
   1.170 +    return eval("'" + str + "'");
   1.171 +}
   1.172 +
   1.173 +
   1.174 +function addThis()
   1.175 +{
   1.176 +  statusitems[UBound] = status;
   1.177 +  actualvalues[UBound] = actual;
   1.178 +  expectedvalues[UBound] = expect;
   1.179 +  UBound++;
   1.180 +}
   1.181 +
   1.182 +
   1.183 +function test()
   1.184 +{
   1.185 +  enterFunc('test');
   1.186 +  printBugNumber(BUGNUMBER);
   1.187 +  printStatus(summary);
   1.188 +
   1.189 +  for (var i=0; i<UBound; i++)
   1.190 +  {
   1.191 +    reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]);
   1.192 +  }
   1.193 +
   1.194 +  exitFunc ('test');
   1.195 +}

mercurial