You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
3.0 KiB

4 years ago
  1. import { decode } from "@webassemblyjs/wasm-parser";
  2. import { traverse } from "@webassemblyjs/ast";
  3. import { cloneNode } from "@webassemblyjs/ast/lib/clone";
  4. import { shrinkPaddedLEB128 } from "@webassemblyjs/wasm-opt";
  5. import { getSectionForNode } from "@webassemblyjs/helper-wasm-bytecode";
  6. import constants from "@webassemblyjs/helper-wasm-bytecode";
  7. import { applyOperations } from "./apply";
  8. function hashNode(node) {
  9. return JSON.stringify(node);
  10. }
  11. function preprocess(ab) {
  12. var optBin = shrinkPaddedLEB128(new Uint8Array(ab));
  13. return optBin.buffer;
  14. }
  15. function sortBySectionOrder(nodes) {
  16. var originalOrder = new Map();
  17. var _iteratorNormalCompletion = true;
  18. var _didIteratorError = false;
  19. var _iteratorError = undefined;
  20. try {
  21. for (var _iterator = nodes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
  22. var _node = _step.value;
  23. originalOrder.set(_node, originalOrder.size);
  24. }
  25. } catch (err) {
  26. _didIteratorError = true;
  27. _iteratorError = err;
  28. } finally {
  29. try {
  30. if (!_iteratorNormalCompletion && _iterator.return != null) {
  31. _iterator.return();
  32. }
  33. } finally {
  34. if (_didIteratorError) {
  35. throw _iteratorError;
  36. }
  37. }
  38. }
  39. nodes.sort(function (a, b) {
  40. var sectionA = getSectionForNode(a);
  41. var sectionB = getSectionForNode(b);
  42. var aId = constants.sections[sectionA];
  43. var bId = constants.sections[sectionB];
  44. if (typeof aId !== "number" || typeof bId !== "number") {
  45. throw new Error("Section id not found");
  46. }
  47. if (aId === bId) {
  48. // $FlowIgnore originalOrder is filled for all nodes
  49. return originalOrder.get(a) - originalOrder.get(b);
  50. }
  51. return aId - bId;
  52. });
  53. }
  54. export function edit(ab, visitors) {
  55. ab = preprocess(ab);
  56. var ast = decode(ab);
  57. return editWithAST(ast, ab, visitors);
  58. }
  59. export function editWithAST(ast, ab, visitors) {
  60. var operations = [];
  61. var uint8Buffer = new Uint8Array(ab);
  62. var nodeBefore;
  63. function before(type, path) {
  64. nodeBefore = cloneNode(path.node);
  65. }
  66. function after(type, path) {
  67. if (path.node._deleted === true) {
  68. operations.push({
  69. kind: "delete",
  70. node: path.node
  71. }); // $FlowIgnore
  72. } else if (hashNode(nodeBefore) !== hashNode(path.node)) {
  73. operations.push({
  74. kind: "update",
  75. oldNode: nodeBefore,
  76. node: path.node
  77. });
  78. }
  79. }
  80. traverse(ast, visitors, before, after);
  81. uint8Buffer = applyOperations(ast, uint8Buffer, operations);
  82. return uint8Buffer.buffer;
  83. }
  84. export function add(ab, newNodes) {
  85. ab = preprocess(ab);
  86. var ast = decode(ab);
  87. return addWithAST(ast, ab, newNodes);
  88. }
  89. export function addWithAST(ast, ab, newNodes) {
  90. // Sort nodes by insertion order
  91. sortBySectionOrder(newNodes);
  92. var uint8Buffer = new Uint8Array(ab); // Map node into operations
  93. var operations = newNodes.map(function (n) {
  94. return {
  95. kind: "add",
  96. node: n
  97. };
  98. });
  99. uint8Buffer = applyOperations(ast, uint8Buffer, operations);
  100. return uint8Buffer.buffer;
  101. }