text: /*
   *  Testcases for E5 to E5.1 corrections, Appendix F of the
   *  E5.1 specification.
   */
  
  /*===
  foobar
  barfoo
  ===*/
  
  /* 7.8.4: CV definitions added for DoubleStringCharacter :: LineContinuation and SingleStringCharacter ::
   * LineContinuation.
   *
   * (The character value (CV) is defined to be the empty character.)
   */
  
  try {
      print("foo\
  bar");
      print('bar\
  foo');
  } catch (e) {
      print(e);
  }
  
  /*===
  imm1
  function
  function
  imm2
  function
  TypeError
  should not be modified
  ===*/
  
  /* 10.2.1.1.3: The argument S is not ignored. It controls whether an exception is
   * thrown when attempting to set an immutable binding.
   *
   * (There are not very many immutable bindings in the spec.  One of them is
   * the name of a named function expression.  Assigning to it should be silently
   * ignored in non-strict mode and a TypeError in strict mode.)
   */
  
  var func = 'should not be modified';
  var immutable1 = function func() { print('imm1'); print(typeof func); func = 123; print(typeof func); }
  var immutable2 = function func() { 'use strict'; print('imm2'); print(typeof func); func = 123; print(typeof func); }
  try { immutable1(); } catch(e) { print(e); }
  try { immutable2(); } catch(e) { print(e.name); }
  print(func);
  
  /*===
  ===*/
  
  /* 10.2.1.2.2: In algorithm step 5, true is passed as the last argument to [[DefineOwnProperty]].
   *
   * (Step 3 asserts that the property does not exist to begin with, so this
   * looks like a purely technical change with no behavioral impact.)
   */
  
  /*===
  ===*/
  
  /* 10.5: Former algorithm step 5.e is now 5.f and a new step 5.e was added to restore compatibility with 3rd
   * Edition when redefining global functions.
   *
   * (Separate testcases: test-spec-redeclare-global*.js)
   */
  
  /*===
  ===*/
  
  /* 11.5.3: In the final bullet item, use of IEEE 754 round-to-nearest mode is specified.
   *
   * (No test.)
   */
  
  /*===
  for 1st
  for 2nd
  ===*/
  
  /* 12.6.3: Missing ToBoolean restored in step 3.a.ii of both algorithms.
   *
   * (Already implemented this way, easily demonstrated with a test.)
   */
  
  function forToBooleanTest() {
      var i;
  
      // 0 is 'falsy' and terminates loop
      print('for 1st');
      for (i = 0; 0; i++) {
          print('never here');
          break;  // in case we are, break out
      }
  
      print('for 2nd');
      for (var j = 0; 0; j++) {
          print('never here');
          break;
      }
  }
  
  try {
      forToBooleanTest();
  } catch (e) {
      print(e);
  }
  
  /*===
  ===*/
  
  /* 12.6.4: Additional final sentences in each of the last two paragraphs clarify certain
   * property enumeration requirements.
   *
   * (Already covered by enumeration tests.)
   */
  
  /*===
  switch-break
  undefined
  for-continue
  undefined
  function-return
  undefined
  ===*/
  
  /* 12.7, 12.8, 12.9: BNF modified to clarify that a continue or break statement without an
   * Identifier or a return statement without an Expression may have a LineTerminator before
   * the semi-colon.
   *
   * (If automatic semicolon insertion kicks in instead, the following semi-colon
   * would be interpreted as an empty statement.  This doesn't usually matter but
   * it does matter e.g. in a naked "if () X else Y".)
   */
  
  /* break/continue tests are simply syntax tests */
  try {
      print('switch-break');
      print(eval('(function() { switch(123) { case 123: break\n; }; })()'));
  } catch (e) {
      print(e);
  }
  
  try {
      print('for-continue');
     print(eval('(function() { for (;;) { break; continue\n; } })()'));
  } catch (e) {
      print(e);
  }
  
  try {
      /* if 'return\n;' is parsed as 'return; ;' it would make the if-statement
       * invalid, so this is a more useful test.
       */
      print('function-return');
      print(eval('(function() { if (true) return\n;else return 234 })()'));
  } catch (e) {
      print(e);
  }
  
  /*===
  ===*/
  
  /* 12.14: Step 3 of algorithm 1 and step 2.a of algorithm 3 are corrected such
   * that the value field of B is passed as a parameter rather than B itself.
   *
   * (No relevant test.)
   */
  
  /*===
  NaN
  NaN
  ===*/
  
  /* 15.1.2.2: In step 2 of algorithm, clarify that S may be the empty string.
   *
   * (Already works, demonstrate with empty string: NaN is provided by step 12.)
   */
  
  try {
      print(parseInt(''));
      print(parseInt('    '));
  } catch (e) {
      print(e);
  }
  
  /*===
  NaN
  NaN
  ===*/
  
  /* 15.1.2.3: In step 2 of algorithm clarify that trimmedString may be the empty string.
   *
   * (Already works, demonstrate with empty string: NaN is provided by step 3,
   * as empty string doesn't match StrDecimalLiteral.)
   */
  
  try {
      print(parseFloat(''));
      print(parseFloat('    '));
  } catch (e) {
      print(e);
  }
  
  /*===
  %23[]!'()*
  #%5B%5D!'()*
  ===*/
  
  /* 15.1.3: Added notes clarifying that ECMAScript‘s URI syntax is based upon RFC 2396
   * and not the newer RFC 3986. In the algorithm for Decode, a step was removed that
   * immediately preceded the current step 4.d.vii.10.a because it tested for a condition
   * that cannot occur.
   *
   * (The URI syntax changes between RFC 2396 and RFC 3986 don't affect URI
   * decoding in Ecmascript, but e.g. reserved character set has changed.  See
   * doc/uri.txt for discussion.)
   */
  
  try {
      print(decodeURI("%23%5B%5D%21%27%28%29%2A"));
      print(encodeURI("#[]!'()*"));
  } catch (e) {
      print(e);
  }
  
  /*===
  ===*/
  
  /* 15.2.3.7: Corrected use of variable P in steps 5 and 6 of algorithm.
   *
   * (No test.)
   */
  
  /*===
  [object Undefined]
  [object Null]
  ===*/
  
  /* 15.2.4.2: Edition 5 handling of undefined and null as this value caused existing code to fail. Specification
   * modified to maintain compatibility with such code. New steps 1 and 2 added to the algorithm.
   */
  
  try { print(Object.prototype.toString.call(undefined)); } catch (e) { print(e); }
  try { print(Object.prototype.toString.call(null)); } catch (e) { print(e); }
  
  /*===
  apply: mythis foo bar quux
  apply: mythis undefined undefined undefined
  apply: mythis undefined undefined undefined
  apply: mythis undefined undefined undefined
  apply: mythis undefined undefined undefined
  apply: mythis foo undefined undefined
  ===*/
  
  /* 15.3.4.3: Steps 5 and 7 of Edition 5 algorithm have been deleted because they imposed requirements upon
   * the argArray argument that are inconsistent with other uses of generic array-like objects.
   *
   * (This only affects apply() calls where argArray is an object, but not an
   * Array, so it may have an arbitrary or missing 'length' value.  E5.1 states
   * that ToUint32() coercion is blindly done: undefined/null length coerces to
   * 0 instead of causing a TypeError.)
   */
  
  function applyTest(x,y,z) { print('apply:', this, x, y, z); }
  
  try { applyTest.apply('mythis', [ 'foo', 'bar', 'quux' ]) } catch (e) { print(e); }
  
  // no length -> 0
  try { applyTest.apply('mythis', { "0": 'foo', "1": 'bar', "2": 'quux' }) } catch (e) { print(e); }
  
  // undefined or null length -> 0
  try { applyTest.apply('mythis', { "0": 'foo', "1": 'bar', "2": 'quux', "length": undefined }) } catch (e) { print(e); }
  try { applyTest.apply('mythis', { "0": 'foo', "1": 'bar', "2": 'quux', "length": null }) } catch (e) { print(e); }
  
  // already required by E5, false->0, true->1
  try { applyTest.apply('mythis', { "0": 'foo', "1": 'bar', "2": 'quux', "length": false }) } catch (e) { print(e); }
  try { applyTest.apply('mythis', { "0": 'foo', "1": 'bar', "2": 'quux', "length": true }) } catch (e) { print(e); }
  
  /*===
  ===*/
  
  /* 15.4.4.12: In step 9.a, incorrect reference to relativeStart was replaced
   * with a reference to actualStart.
   *
   * (Implementation already worked in E5.1 fashion.)
   */
  
  /*===
  ===*/
  
  /* 15.4.4.15: Clarified that the default value for fromIndex is the length
   * minus 1 of the array.
   *
   * (Implemented already worked in E5.1 fashion.)
   */
  
  /*===
  forEach: 1
  forEach: 2
  forEach: 3
  undefined
  ===*/
  
  /* 15.4.4.18: In step 9 of the algorithm, undefined is now the specified return value. */
  
  try {
      print([1,2,3].forEach(function(x) { print('forEach:', x); }));
  
  } catch (e) {
      print(e);
  }
  
  /*===
  reduce: 1 2 1 1,2,3
  reduce this: undefined undefined
  reduce: 3 3 2 1,2,3
  reduce this: undefined undefined
  6
  reduceRight: 3 2 1 1,2,3
  reduceRight this: undefined undefined
  reduceRight: 5 1 0 1,2,3
  reduceRight this: undefined undefined
  6
  ===*/
  
  /* 15.4.4.22: In step 9.c.ii the first argument to the [[Call]] internal method has been
   * changed to undefined for consistency with the definition of Array.prototype.reduce.
   *
   * (Test 'this' binding, must use a strict function to get in unmangled.)
   */
  
  try {
      print([1,2,3].reduce(function(accumulator, kValue, k, O) {
          'use strict';
          print('reduce:', accumulator, kValue, k, O);
          print('reduce this:', typeof this, this);
          return accumulator + kValue;  // sum
      }));
  } catch (e) {
      print(e);
  }
  
  try {
      print([1,2,3].reduceRight(function(accumulator, kValue, k, O) {
          'use strict';
          print('reduceRight:', accumulator, kValue, k, O);
          print('reduceRight this:', typeof this, this);
          return accumulator + kValue;  // sum
      }));
  } catch (e) {
      print(e);
  }
  
  /*===
  ===*/
  
  /* 15.4.5.1: In Algorithm steps 3.l.ii and 3.l.iii the variable name was inverted resulting
   * in an incorrectly inverted test.
   *
   * (Handled correctly by handle_put_array_length_smaller() in duk_hobject_props.c.)
   */
  
  /*===
  ===*/
  
  /* 15.5.4.9: Normative requirement concerning canonically equivalent strings deleted from paragraph following
   * algorithm because it is listed as a recommendation in NOTE 2.
   *
   * (No test.)
   */
  
  /*===
  ===*/
  
  /* 15.5.4.14: In split algorithm step 11.a and 13.a, the positional order of the arguments to SplitMatch was
   * corrected to match the actual parameter signature of SplitMatch. In step 13.a.iii.7.d, lengthA replaces A.length.
   *
   * (Obvious typo fixes, no test.  Current implementation is based on E5.1 anyway.)
   */
  
  /*===
  ===*/
  
  /* 15.5.5.2: In first paragraph, removed the implication that the individual character property access had array
   * index semantics. Modified algorithm steps 3 and 5 such that they do not enforce array index requirement.
   *
   * (This change matters only for strings longer than 4G characters which Duktape
   * doesn't support at the moment anyway, so there is no way to test.  Added a Ditz
   * issue for tracking that a fix is done if it becomes relevant.)
   */
  
  /*===
  ===*/
  
  /* 15.9.1.15: Specified legal value ranges for fields that lacked them. Eliminated time-only formats. Specified
   * default values for all optional fields.
   *
   * (Already implemented to E5.1 requirements, no test.)
   */
  
  /*===
  ===*/
  
  /* 15.10.2.2: The step numbers of the algorithm for the internal closure produced by step 2 were incorrectly
   * numbered in a manner that implied that they were steps of the outer algorithm.
   *
   * (Obvious typo.)
   */
  
  /*===
  ===*/
  
  /* 15.10.2.6: In the abstract operation IsWordChar the first character in the list in step 3 is a rather than A.
   *
   * (Obvious typo.)
   */
  
  /*===
  ===*/
  
  /* 15.10.2.8: In the algorithm for the closure returned by the abstract operation CharacterSetMatcher, the variable
   * defined by step 3 and passed as an argument in step 4 was renamed to ch in order to avoid a name conflict
   * with a formal parameter of the closure.
   *
   * (No test.)
   */
  
  /*===
  ===*/
  
  /* 15.10.6.2: Step 9.e was deleted because It performed an extra increment of i.
   *
   * (Obvious typo, handled correctly in regexp code; no test.)
   */
  
  /*===
  object
  object
  undefined
  ""
  ===*/
  
  /* 15.11.1.1: Removed requirement that the message own property is set to the empty String when the message
   * argument is undefined.
   *
   * (It's preferable not to set the own property 'message' when the argument
   * is undefined because it saves a property slot; an empty message is
   * inherited automatically anyway.  Funnily enough, this entry appears three
   * times in the E5.1 Appendix F, and two of the occurrences refer a non-existent
   * Section 15.11.1.2 :-)
   */
  
  function errMessageTest1() {
      var e1 = new Error('foo');
      var e2 = new Error('');
      var e3 = new Error();
      print(typeof Object.getOwnPropertyDescriptor(e1, 'message'));
      print(typeof Object.getOwnPropertyDescriptor(e2, 'message'));
      print(typeof Object.getOwnPropertyDescriptor(e3, 'message'));
      print(JSON.stringify(e3.message));
  }
  
  try {
      errMessageTest1();
  } catch (e) {
      print(e);
  }
  
  /*===
  "Error"
  "Error"
  ===*/
  
  /* 15.11.4.4: Steps 6-10 modified/added to correctly deal with missing or empty message property value. */
  
  function errMessageTest2() {
      var e1 = new Error();
      var e2 = new Error('');
      print(JSON.stringify(e1.toString()));
      print(JSON.stringify(e2.toString()));
  }
  
  try {
      errMessageTest2();
  } catch (e) {
      print(e);
  }
  
  /*===
  ===*/
  
  /* 15.12.3: In step 10.b.iii of the JA internal operation, the last element of the concatenation is ].
   *
   * (No test, obvious typo fix in spec.)
   */
  
  /*===
  ===*/
  
  /* B.2.1: Added to NOTE that the encoding is based upon RFC 1738 rather than the newer RFC 3986.
   *
   * (No test, as there is no change in the algorithm itself.)
   */
  
  /*===
  ===*/
  
  /* Annex C: An item was added corresponding to 7.6.12 regarding FutureReservedWords in strict mode.
   *
   * (No test.)
   */
  
  