apply3.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. function echo(msg) {
  6. WScript.Echo(msg);
  7. }
  8. function guarded_call(func) {
  9. try {
  10. func();
  11. } catch(e) {
  12. echo("Exception: " + e.name + " : " + e.message);
  13. }
  14. }
  15. function dump_args() {
  16. var args = "";
  17. for (var i = 0; i < arguments.length; i++) {
  18. if (i > 0) {
  19. args += ", ";
  20. }
  21. args += arguments[i];
  22. }
  23. echo("Called with this: " + typeof this + "[" + this + "], args: [" + args + "]");
  24. }
  25. // 1. If IsCallable(func) is false, throw TypeError
  26. var noncallable = {
  27. apply: Function.prototype.apply
  28. };
  29. echo("--- f is not callable ---");
  30. guarded_call(function() {
  31. noncallable.apply();
  32. });
  33. guarded_call(function() {
  34. noncallable.apply({}, [1, 2, 3]);
  35. });
  36. // 2. If argArray is null or undefined, call func with an emply list of arguments
  37. var o = {};
  38. echo("\n--- f.apply(x) ---");
  39. guarded_call(function() {
  40. dump_args.apply(o);
  41. });
  42. echo("\n--- f.apply(x, null), f.apply(x, undefined) ---");
  43. guarded_call(function() {
  44. dump_args.apply(o, null);
  45. });
  46. guarded_call(function() {
  47. dump_args.apply(o, undefined);
  48. });
  49. // 3. Type(argArray) is invalid
  50. echo("\n--- f.apply(x, 123), f.apply(x, 'string'), f.apply(x, true) ---");
  51. guarded_call(function() {
  52. dump_args.apply(o, 123);
  53. });
  54. guarded_call(function() {
  55. dump_args.apply(o, 'string');
  56. });
  57. guarded_call(function() {
  58. dump_args.apply(o, true);
  59. });
  60. // 5, 7 argArray.length is invalid
  61. echo("\n--- f.apply(x, obj), obj.length is null/undefined/NaN/string/OutOfRange ---");
  62. guarded_call(function() {
  63. dump_args.apply(o, {length: null});
  64. });
  65. guarded_call(function() {
  66. dump_args.apply(o, {length: undefined});
  67. });
  68. guarded_call(function() {
  69. dump_args.apply(o, {length: NaN});
  70. });
  71. guarded_call(function() {
  72. dump_args.apply(o, {length: 'string'});
  73. });
  74. guarded_call(function() {
  75. dump_args.apply(o, {length: 4294967295 + 1}); //UINT32_MAX + 1
  76. });
  77. guarded_call(function() {
  78. dump_args.apply(o, {length: -1});
  79. });
  80. echo("\n--- f.apply(x, arr), arr.length is huge ---");
  81. var huge_array_length = [];
  82. huge_array_length.length = 2147483647; //INT32_MAX
  83. guarded_call(function() {
  84. dump_args.apply(o, huge_array_length);
  85. });
  86. echo("\n--- f.apply(x, obj), obj.length is huge ---");
  87. guarded_call(function() {
  88. dump_args.apply(o, {length: 4294967295}); //UINT32_MAX
  89. });
  90. // Normal usage -- argArray tests
  91. echo("\n--- f.apply(x, arr) ---");
  92. dump_args.apply(o, []);
  93. dump_args.apply(o, [1]);
  94. dump_args.apply(o, [2, 3, NaN, null, undefined, false, "hello", o]);
  95. echo("\n--- f.apply(x, arr) arr.length increased ---");
  96. var arr = [1, 2];
  97. arr.length = 5;
  98. dump_args.apply(o, arr);
  99. echo("\n--- f.apply(x, arguments) ---");
  100. function apply_arguments() {
  101. dump_args.apply(o, arguments);
  102. }
  103. apply_arguments();
  104. apply_arguments(1);
  105. apply_arguments(2, 3, NaN, null, undefined, false, "hello", o);
  106. echo("\n--- f.apply(x, obj) ---");
  107. guarded_call(function() {
  108. dump_args.apply(o, {
  109. length: 0
  110. });
  111. });
  112. guarded_call(function() {
  113. dump_args.apply(o, {
  114. length: 1,
  115. "0": 1
  116. });
  117. });
  118. guarded_call(function() {
  119. dump_args.apply(o, {
  120. length: 8,
  121. "0": 2,
  122. "1": 3,
  123. "2": NaN,
  124. "3": null,
  125. "4": undefined,
  126. "5": false,
  127. "6": "hello",
  128. "7": o
  129. });
  130. });
  131. // Normal usage -- thisArg tests
  132. function f1() {
  133. this.x1 = "hello";
  134. }
  135. echo("\n--- f.apply(), f.apply(null), f.apply(undefined), global x1 should be changed ---");
  136. f1.apply();
  137. echo("global x1 : " + x1);
  138. x1 = 0;
  139. f1.apply(null);
  140. echo("global x1 : " + x1);
  141. x1 = 0;
  142. f1.apply(undefined);
  143. echo("global x1 : " + x1);
  144. echo("\n--- f.apply(x), global x1 should NOT be changed ---");
  145. var o = {};
  146. x1 = 0;
  147. f1.apply(o);
  148. echo("global x1 : " + x1);
  149. echo("o.x1 : " + o.x1);
  150. // apply on non-objects -- test thisArg
  151. function apply_non_object(func, doEcho) {
  152. var echo_if = function(msg) {
  153. if (doEcho) {
  154. echo(msg);
  155. }
  156. };
  157. guarded_call(function() {
  158. echo_if(func.apply());
  159. });
  160. guarded_call(function() {
  161. echo_if(func.apply(null));
  162. });
  163. guarded_call(function() {
  164. echo_if(func.apply(undefined));
  165. });
  166. guarded_call(function() {
  167. echo_if(func.apply(123));
  168. });
  169. guarded_call(function() {
  170. echo_if(func.apply(true));
  171. });
  172. guarded_call(function() {
  173. echo_if(func.apply("string"));
  174. });
  175. }
  176. echo("\n--- f.apply(v), v is missing/null/undefined/123/true/'string' ---");
  177. apply_non_object(dump_args);
  178. //
  179. // ES5: String.prototype.charCodeAt calls CheckObjectCoercible(thisArg). It should throw
  180. // when thisArg is missing/null/undefined.
  181. //
  182. echo("\n--- f.apply(v), v is missing/null/undefined/123/true/'string', f: string.charCodeAt ---");
  183. apply_non_object(String.prototype.charCodeAt, true);
  184. echo("\n--- f.apply(v), v is missing/null/undefined/123/true/'string', f: string.charAt ---");
  185. apply_non_object(String.prototype.charAt, true);
  186. //
  187. // Similarly, test thisArg behavior in Function.prototype.call
  188. //
  189. // call on non-objects -- test thisArg
  190. function call_non_object(func, doEcho) {
  191. var echo_if = function(msg) {
  192. if (doEcho) {
  193. echo(msg);
  194. }
  195. };
  196. guarded_call(function() {
  197. echo_if(func.call());
  198. });
  199. guarded_call(function() {
  200. echo_if(func.call(null));
  201. });
  202. guarded_call(function() {
  203. echo_if(func.call(undefined));
  204. });
  205. guarded_call(function() {
  206. echo_if(func.call(123));
  207. });
  208. guarded_call(function() {
  209. echo_if(func.call(true));
  210. });
  211. guarded_call(function() {
  212. echo_if(func.call("string"));
  213. });
  214. }
  215. echo("\n--- f.call(v), v is missing/null/undefined/123/true/'string' ---");
  216. call_non_object(dump_args);
  217. echo("\n--- f.call(v), v is missing/null/undefined/123/true/'string', f: string.charCodeAt ---");
  218. call_non_object(String.prototype.charCodeAt, true);
  219. echo("\n--- f.call(v), v is missing/null/undefined/123/true/'string', f: string.charAt ---");
  220. call_non_object(String.prototype.charAt, true);