response.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. WScript.Flag("-wasmIgnoreResponse");
  6. const setTimeout = WScript.SetTimeout;
  7. // Shim the response api
  8. class Response {
  9. constructor(buffer, shouldFail) {
  10. this.buffer = buffer;
  11. this.shouldFail = shouldFail;
  12. }
  13. arrayBuffer() {
  14. return new Promise((resolve, reject) => {
  15. setTimeout(() => {
  16. if (this.shouldFail) {
  17. return reject(new Error("Unable to fetch the buffer"));
  18. }
  19. resolve(this.buffer);
  20. }, 100);
  21. });
  22. }
  23. }
  24. function fetch(getBuffer) {
  25. return new Promise((resolve, reject) => {
  26. setTimeout(() => {
  27. try {
  28. resolve(new Response(getBuffer()));
  29. } catch (e) {
  30. reject(e);
  31. }
  32. }, 100);
  33. });
  34. }
  35. const defaultModule = WebAssembly.wabt.convertWast2Wasm(`
  36. (module
  37. (func (export "foo") (result i32) (i32.const 5))
  38. )`);
  39. function validateDefaultInstance({exports: {foo}}) {
  40. const res = foo();
  41. if (res !== 5) {
  42. throw new Error(`Bad result: ${res} !== 5`);
  43. }
  44. }
  45. function validateDefaultCompile(module) {
  46. validateDefaultInstance(new WebAssembly.Instance(module));
  47. }
  48. function validateDefaultInstantiate({module, instance}) {
  49. validateDefaultCompile(module);
  50. validateDefaultInstance(instance);
  51. }
  52. const defaultImportModule = WebAssembly.wabt.convertWast2Wasm(`
  53. (module
  54. (global $iImport (import "test" "i32") i32)
  55. (import "test" "foo" (func $foo (result i32)))
  56. (func (export "foo") (result i32) (call $foo) (get_global $iImport) (i32.add))
  57. )`);
  58. const defaultImportObject = {test: {i32: 3, foo: () => -2}};
  59. function validateDefaultImportInstance({exports: {foo}}) {
  60. const res = foo();
  61. const expected = (defaultImportObject.test.i32 + defaultImportObject.test.foo())|0;
  62. if (res !== expected) {
  63. throw new Error(`Bad result: ${res} !== ${expected}`);
  64. }
  65. }
  66. function validateDefaultImportInstantiate({module, instance}) {
  67. validateDefaultImportInstance(new WebAssembly.Instance(module, defaultImportObject));
  68. validateDefaultImportInstance(instance);
  69. }
  70. const tests = [];
  71. let allTestsQueued = false;
  72. const allTestsDone = () => !tests.find(info => info.state !== "done");
  73. function checkIfAllDone() {
  74. if (allTestsQueued && allTestsDone()) {
  75. report();
  76. }
  77. }
  78. function test(fn, description) {
  79. const testInfo = {
  80. state: "pending",
  81. description
  82. };
  83. tests.push(testInfo);
  84. const done = () => {
  85. testInfo.state = "done";
  86. checkIfAllDone();
  87. };
  88. try {
  89. testInfo.state = "testing";
  90. const p = fn();
  91. p.then(() => {
  92. testInfo.result = "Passed";
  93. }, e => {
  94. testInfo.result = "Failed";
  95. testInfo.error = e;
  96. }).then(done);
  97. } catch (e) {
  98. // If fn doesn't return a Promise we will throw here
  99. // WebAssembly.compileStreaming should always return a Promise
  100. testInfo.result = "Failed";
  101. testInfo.error = e;
  102. done();
  103. }
  104. }
  105. function shouldThrow() {
  106. throw new Error("Should have had an error");
  107. }
  108. function ignoreError() {}
  109. test(() =>
  110. WebAssembly.compileStreaming(defaultModule)
  111. .then(shouldThrow, ignoreError),
  112. "WebAssembly.compileStreaming(buffer => Error)"
  113. );
  114. test(() =>
  115. WebAssembly.compileStreaming(new Promise((resolve, reject) => setTimeout(() => reject(new Error("Some Error")), 100)))
  116. .then(shouldThrow, ignoreError),
  117. "WebAssembly.compileStreaming(Promise => timeout Error)"
  118. );
  119. test(() =>
  120. WebAssembly.compileStreaming(Promise.reject())
  121. .then(shouldThrow, ignoreError),
  122. "WebAssembly.compileStreaming(Promise => Empty Error)"
  123. );
  124. test(() =>
  125. WebAssembly.compileStreaming(Promise.reject(new Error("Promise.reject(new Error()")))
  126. .then(shouldThrow, ignoreError),
  127. "WebAssembly.compileStreaming(Promise => Error)"
  128. );
  129. test(() =>
  130. WebAssembly.compileStreaming(Promise.resolve("Wrong type"))
  131. .then(shouldThrow, ignoreError),
  132. "WebAssembly.compileStreaming(Promise => string)"
  133. );
  134. test(() =>
  135. WebAssembly.compileStreaming(fetch(() => defaultModule))
  136. .then(validateDefaultCompile),
  137. "WebAssembly.compileStreaming(fetch => defaultModule)"
  138. );
  139. test(() =>
  140. WebAssembly.compileStreaming(fetch(() => {throw new Error("Failed to fetch");}))
  141. .then(shouldThrow, ignoreError),
  142. "WebAssembly.compileStreaming(fetch => Error)"
  143. );
  144. test(() =>
  145. WebAssembly.compileStreaming(new Response(defaultModule))
  146. .then(validateDefaultCompile),
  147. "WebAssembly.compileStreaming(Response => defaultModule)"
  148. );
  149. test(() =>
  150. WebAssembly.compileStreaming(new Response(defaultModule, true))
  151. .then(shouldThrow, ignoreError),
  152. "WebAssembly.compileStreaming(Response => Error)"
  153. );
  154. test(() =>
  155. WebAssembly.instantiateStreaming(defaultModule)
  156. .then(shouldThrow, ignoreError),
  157. "WebAssembly.instantiateStreaming(defaultModule => Error)"
  158. );
  159. test(() =>
  160. WebAssembly.instantiateStreaming(fetch(() => defaultModule))
  161. .then(validateDefaultInstantiate),
  162. "WebAssembly.instantiateStreaming(fetch => defaultModule)"
  163. );
  164. test(() =>
  165. WebAssembly.instantiateStreaming(fetch(() => {throw new Error("Failed to fetch");}))
  166. .then(shouldThrow, ignoreError),
  167. "WebAssembly.instantiateStreaming(fetch => Error)"
  168. );
  169. test(() =>
  170. WebAssembly.instantiateStreaming(new Response(defaultModule))
  171. .then(validateDefaultInstantiate),
  172. "WebAssembly.instantiateStreaming(Response => defaultModule)"
  173. );
  174. test(() =>
  175. WebAssembly.instantiateStreaming(new Response(defaultModule, true))
  176. .then(shouldThrow, ignoreError),
  177. "WebAssembly.instantiateStreaming(Response => Error)"
  178. );
  179. test(() =>
  180. WebAssembly.instantiateStreaming(fetch(() => defaultImportModule), defaultImportObject)
  181. .then(validateDefaultImportInstantiate),
  182. "WebAssembly.instantiateStreaming(fetch => defaultImportModule, defaultImportObject)"
  183. );
  184. test(() =>
  185. WebAssembly.instantiateStreaming(new Response(defaultImportModule), defaultImportObject)
  186. .then(validateDefaultImportInstantiate),
  187. "WebAssembly.instantiateStreaming(Response => defaultImportModule, defaultImportObject)"
  188. );
  189. allTestsQueued = true;
  190. // In case all the test ran synchronously
  191. checkIfAllDone();
  192. function report() {
  193. const status = {};
  194. tests.forEach(info => {
  195. status[info.result] = (status[info.result]|0) + 1;
  196. const error = info.error ? "\n" + info.error.stack : "";
  197. console.log(`${info.result}: ${info.description}${error}`);
  198. });
  199. const statusReport = Object.keys(status)
  200. .map(state => `${state}=${status[state]}`)
  201. .join(", ");
  202. console.log(`Report: ${statusReport}`);
  203. }