params.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. function* paramTypes() {
  6. while (true) {
  7. yield "i32";
  8. yield "f32";
  9. yield "f64";
  10. }
  11. }
  12. function* callArguments() {
  13. while (true) {
  14. yield {value: -12345, i32: "-12345", f32: `fr(${Math.fround(-12345)})`, f64: "-12345.0"};
  15. yield {value: Math.PI, i32: `${Math.PI|0}`, f32: `fr(${Math.fround(Math.PI)})`, f64: `+${Math.PI}`};
  16. }
  17. }
  18. function wrapType(type, name) {
  19. switch (type) {
  20. case "i32": return `${name}|0`;
  21. case "f32": return `fr(${name})`;
  22. case "f64": return `+${name}`;
  23. default: throw new Error("Invalid Type");
  24. }
  25. }
  26. const tested = {};
  27. function test(n) {
  28. if (n in tested) {
  29. return tested[n];
  30. }
  31. print(`Test(${n})`);
  32. const typeGen = paramTypes();
  33. const argGen = callArguments();
  34. const params = [], callArgs = [], verify = [];
  35. for (let i = 0; i < n; ++i) {
  36. const type = typeGen.next().value;
  37. const paramName = `a${i|0}`;
  38. const arg = argGen.next().value;
  39. params.push({type, name: paramName});
  40. callArgs.push(arg.value);
  41. verify.push(`if (${wrapType(type, paramName)} != ${arg[type]}) return 1;`);
  42. }
  43. const paramList = params.map(p => p.name).join(",");
  44. const paramsTypes = params.map(({type, name}) => `${name} = ${wrapType(type, name)}`).join("; ");
  45. const txt = `
  46. return function AsmModule(stdlib) {
  47. "use asm";
  48. var fr = stdlib.Math.fround;
  49. function verify(${paramList}) {
  50. ${paramsTypes};
  51. ${verify.join("\n")}
  52. return 0;
  53. }
  54. function foo(${paramList}) {
  55. ${paramsTypes}
  56. return verify(${paramList})|0;
  57. }
  58. return foo;
  59. }`;
  60. //print(txt);
  61. try {
  62. var AsmModule = (new Function(txt))();
  63. var foo = AsmModule({Math});
  64. if (foo(...callArgs) !== 1) {
  65. print(`FAILED. Failed to validate with ${n} arguments`);
  66. }
  67. tested[n] = true;
  68. return true;
  69. } catch (e) {
  70. }
  71. tested[n] = false;
  72. }
  73. const [forceTest] = WScript.Arguments;
  74. if (forceTest !== undefined) {
  75. const res = test(forceTest);
  76. print(res ? "Module is valid" : "Module is invalid");
  77. WScript.Quit(0);
  78. }
  79. let nParams = 8201;
  80. let inc = 100;
  81. let direction = true;
  82. while (inc !== 0) {
  83. if (test(nParams)) {
  84. if (direction) {
  85. nParams += inc;
  86. } else {
  87. direction = true;
  88. inc >>= 1;
  89. nParams += inc;
  90. }
  91. } else {
  92. if (!direction) {
  93. nParams -= inc;
  94. } else {
  95. direction = false;
  96. inc >>= 1;
  97. nParams -= inc;
  98. }
  99. }
  100. if (nParams > 100000 || nParams < 0) {
  101. print(`FAILED. Params reached ${nParams} long. Expected an error by now`);
  102. break;
  103. }
  104. }
  105. print(`Support at most ${nParams} params`);