memory.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. const cliArgs = WScript.Arguments || [];
  6. if (cliArgs.indexOf("--help") !== -1) {
  7. print("usage: ch memory.js -args [-verbose] -endargs");
  8. WScript.quit(0);
  9. }
  10. // Parse arguments
  11. let verbose = 0;
  12. while (true) {
  13. const iVerbose = cliArgs.indexOf("-verbose");
  14. if (iVerbose === -1) {
  15. break;
  16. }
  17. cliArgs.splice(iVerbose, 1);
  18. ++verbose;
  19. }
  20. function testDetach(buffer) {
  21. try {
  22. ArrayBuffer.detach(buffer);
  23. print("Failed. Expected an error when trying to transfer ");
  24. } catch (e) {
  25. if (verbose > 1) {
  26. print(`Passed. Expected error: ${e.message}`);
  27. }
  28. }
  29. }
  30. function test({init, max, checkOOM} = {}) {
  31. if (verbose) {
  32. print(`Testing memory {init: ${init|0}, max: ${max}}`);
  33. }
  34. const moduleTxt = `
  35. (module
  36. (memory (export "mem") ${init|0} ${max !== undefined ? max|0 : ""})
  37. (func (export "grow") (param i32) (result i32) (grow_memory (get_local 0)))
  38. (func (export "current") (result i32) (current_memory))
  39. (func (export "load") (param i32) (result i32) (i32.load (get_local 0)))
  40. (func (export "store") (param i32 i32) (i32.store (get_local 0) (get_local 1)))
  41. )`;
  42. if (verbose > 1) {
  43. print(moduleTxt);
  44. }
  45. const module = new WebAssembly.Module(WebAssembly.wabt.convertWast2Wasm(moduleTxt));
  46. let instance;
  47. try {
  48. instance = new WebAssembly.Instance(module);
  49. } catch (e) {
  50. if (!checkOOM || !e.message.includes("Failed to create WebAssembly.Memory")) {
  51. print(`FAILED. failed to instanciate module with error: ${e}`);
  52. } else if (verbose) {
  53. print(e.message);
  54. }
  55. return;
  56. }
  57. const {exports: {grow, current, load, store, mem}} = instance;
  58. function testReadWrite(index, value, currentSize) {
  59. const shouldTrap = index < 0 || (index + 4) > currentSize;
  60. const commonMsg = op => `trap on ${op}(${index}, ${value})`;
  61. try {
  62. store(index, value);
  63. if (shouldTrap) {
  64. print(`Failed. Expected ${commonMsg("store")}`);
  65. return;
  66. }
  67. } catch (e) {
  68. if (shouldTrap) {
  69. if (verbose) {
  70. print(`Passed. Expected ${commonMsg("store")}`);
  71. }
  72. } else {
  73. print(`Failed. Unexpected ${commonMsg("store")}`);
  74. }
  75. }
  76. try {
  77. const loadedValue = load(index);
  78. if (shouldTrap) {
  79. print(`Failed. Expected ${commonMsg("load")}`);
  80. return;
  81. }
  82. if ((loadedValue|0) !== (value|0)) {
  83. print(`Failed. Expected value ${value|0} after load. Got ${loadedValue|0}`);
  84. }
  85. } catch (e) {
  86. if (shouldTrap) {
  87. if (verbose) {
  88. print(`Passed. Expected ${commonMsg("load")}`);
  89. }
  90. } else {
  91. print(`Failed. Unexpected ${commonMsg("load")}`);
  92. }
  93. }
  94. }
  95. function run(delta) {
  96. testDetach(mem.buffer);
  97. const beforePages = current();
  98. const growRes = grow(delta);
  99. if (growRes !== -1 && growRes !== beforePages) {
  100. print(`FAILED. Expected grow(${delta}) to return ${beforePages}`);
  101. }
  102. const afterPages = current();
  103. if (growRes !== -1 && beforePages + delta !== afterPages) {
  104. print(`FAILED. Expected to have ${beforePages + delta} pages. Got ${afterPages} pages`);
  105. }
  106. if (verbose) {
  107. print(`current: ${beforePages}, grow(${delta}): ${growRes}, after: ${afterPages}`);
  108. }
  109. const currentSize = afterPages * 0x10000;
  110. testReadWrite(-4, -4, currentSize);
  111. testReadWrite(-3, -3, currentSize);
  112. testReadWrite(-2, -2, currentSize);
  113. testReadWrite(-1, -1, currentSize);
  114. testReadWrite(0, 6, currentSize);
  115. testDetach(mem.buffer);
  116. testReadWrite(1, 7, currentSize);
  117. testDetach(mem.buffer);
  118. testReadWrite(1, 7, currentSize);
  119. testReadWrite(currentSize - 4, 457, currentSize);
  120. testReadWrite(currentSize - 3, -98745, currentSize);
  121. testReadWrite(currentSize - 2, 786452, currentSize);
  122. testReadWrite(currentSize - 1, -1324, currentSize);
  123. testReadWrite(currentSize, 123, currentSize);
  124. testDetach(mem.buffer);
  125. }
  126. run(0);
  127. run(3);
  128. run(5);
  129. run(1 << 13);
  130. }
  131. test({init: 0});
  132. test({init: 0, max: 5});
  133. test({init: 0, max: 10});
  134. test({init: 5});
  135. test({init: 5, max: 10});
  136. // test({init: 1 << 14, checkOOM: true}); // ArrayBuffer will throw OOM instead of returning a null buffer
  137. try {
  138. test({init: 1 << 15});
  139. print("Failed. Expected an error when allocating WebAssembly.Memory too big");
  140. } catch (e) {
  141. if (verbose) {
  142. print(`Passed. Expected error: ${e.message}`);
  143. }
  144. }
  145. print("PASSED");