| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 | "use strict";Object.defineProperty(exports, "__esModule", {  value: true});exports.applyOperations = applyOperations;var _wasmGen = require("@webassemblyjs/wasm-gen");var _encoder = require("@webassemblyjs/wasm-gen/lib/encoder");var _ast = require("@webassemblyjs/ast");var _helperWasmSection = require("@webassemblyjs/helper-wasm-section");var _helperBuffer = require("@webassemblyjs/helper-buffer");var _helperWasmBytecode = require("@webassemblyjs/helper-wasm-bytecode");function _sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }function _slicedToArray(arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return _sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }function shiftLocNodeByDelta(node, delta) {  (0, _ast.assertHasLoc)(node); // $FlowIgnore: assertHasLoc ensures that  node.loc.start.column += delta; // $FlowIgnore: assertHasLoc ensures that  node.loc.end.column += delta;}function applyUpdate(ast, uint8Buffer, _ref) {  var _ref2 = _slicedToArray(_ref, 2),      oldNode = _ref2[0],      newNode = _ref2[1];  var deltaElements = 0;  (0, _ast.assertHasLoc)(oldNode);  var sectionName = (0, _helperWasmBytecode.getSectionForNode)(newNode);  var replacementByteArray = (0, _wasmGen.encodeNode)(newNode);  /**   * Replace new node as bytes   */  uint8Buffer = (0, _helperBuffer.overrideBytesInBuffer)(uint8Buffer, // $FlowIgnore: assertHasLoc ensures that  oldNode.loc.start.column, // $FlowIgnore: assertHasLoc ensures that  oldNode.loc.end.column, replacementByteArray);  /**   * Update function body size if needed   */  if (sectionName === "code") {    // Find the parent func    (0, _ast.traverse)(ast, {      Func: function Func(_ref3) {        var node = _ref3.node;        var funcHasThisIntr = node.body.find(function (n) {          return n === newNode;        }) !== undefined; // Update func's body size if needed        if (funcHasThisIntr === true) {          // These are the old functions locations informations          (0, _ast.assertHasLoc)(node);          var oldNodeSize = (0, _wasmGen.encodeNode)(oldNode).length;          var bodySizeDeltaBytes = replacementByteArray.length - oldNodeSize;          if (bodySizeDeltaBytes !== 0) {            var newValue = node.metadata.bodySize + bodySizeDeltaBytes;            var newByteArray = (0, _encoder.encodeU32)(newValue); // function body size byte            // FIXME(sven): only handles one byte u32            var start = node.loc.start.column;            var end = start + 1;            uint8Buffer = (0, _helperBuffer.overrideBytesInBuffer)(uint8Buffer, start, end, newByteArray);          }        }      }    });  }  /**   * Update section size   */  var deltaBytes = replacementByteArray.length - ( // $FlowIgnore: assertHasLoc ensures that  oldNode.loc.end.column - oldNode.loc.start.column); // Init location informations  newNode.loc = {    start: {      line: -1,      column: -1    },    end: {      line: -1,      column: -1    }  }; // Update new node end position  // $FlowIgnore: assertHasLoc ensures that  newNode.loc.start.column = oldNode.loc.start.column; // $FlowIgnore: assertHasLoc ensures that  newNode.loc.end.column = // $FlowIgnore: assertHasLoc ensures that  oldNode.loc.start.column + replacementByteArray.length;  return {    uint8Buffer: uint8Buffer,    deltaBytes: deltaBytes,    deltaElements: deltaElements  };}function applyDelete(ast, uint8Buffer, node) {  var deltaElements = -1; // since we removed an element  (0, _ast.assertHasLoc)(node);  var sectionName = (0, _helperWasmBytecode.getSectionForNode)(node);  if (sectionName === "start") {    var sectionMetadata = (0, _ast.getSectionMetadata)(ast, "start");    /**     * The start section only contains one element,     * we need to remove the whole section     */    uint8Buffer = (0, _helperWasmSection.removeSections)(ast, uint8Buffer, "start");    var _deltaBytes = -(sectionMetadata.size.value + 1);    /* section id */    return {      uint8Buffer: uint8Buffer,      deltaBytes: _deltaBytes,      deltaElements: deltaElements    };  } // replacement is nothing  var replacement = [];  uint8Buffer = (0, _helperBuffer.overrideBytesInBuffer)(uint8Buffer, // $FlowIgnore: assertHasLoc ensures that  node.loc.start.column, // $FlowIgnore: assertHasLoc ensures that  node.loc.end.column, replacement);  /**   * Update section   */  // $FlowIgnore: assertHasLoc ensures that  var deltaBytes = -(node.loc.end.column - node.loc.start.column);  return {    uint8Buffer: uint8Buffer,    deltaBytes: deltaBytes,    deltaElements: deltaElements  };}function applyAdd(ast, uint8Buffer, node) {  var deltaElements = +1; // since we added an element  var sectionName = (0, _helperWasmBytecode.getSectionForNode)(node);  var sectionMetadata = (0, _ast.getSectionMetadata)(ast, sectionName); // Section doesn't exists, we create an empty one  if (typeof sectionMetadata === "undefined") {    var res = (0, _helperWasmSection.createEmptySection)(ast, uint8Buffer, sectionName);    uint8Buffer = res.uint8Buffer;    sectionMetadata = res.sectionMetadata;  }  /**   * check that the expressions were ended   */  if ((0, _ast.isFunc)(node)) {    // $FlowIgnore    var body = node.body;    if (body.length === 0 || body[body.length - 1].id !== "end") {      throw new Error("expressions must be ended");    }  }  if ((0, _ast.isGlobal)(node)) {    // $FlowIgnore    var body = node.init;    if (body.length === 0 || body[body.length - 1].id !== "end") {      throw new Error("expressions must be ended");    }  }  /**   * Add nodes   */  var newByteArray = (0, _wasmGen.encodeNode)(node); // The size of the section doesn't include the storage of the size itself  // we need to manually add it here  var start = (0, _ast.getEndOfSection)(sectionMetadata);  var end = start;  /**   * Update section   */  var deltaBytes = newByteArray.length;  uint8Buffer = (0, _helperBuffer.overrideBytesInBuffer)(uint8Buffer, start, end, newByteArray);  node.loc = {    start: {      line: -1,      column: start    },    end: {      line: -1,      column: start + deltaBytes    }  }; // for func add the additional metadata in the AST  if (node.type === "Func") {    // the size is the first byte    // FIXME(sven): handle LEB128 correctly here    var bodySize = newByteArray[0];    node.metadata = {      bodySize: bodySize    };  }  if (node.type !== "IndexInFuncSection") {    (0, _ast.orderedInsertNode)(ast.body[0], node);  }  return {    uint8Buffer: uint8Buffer,    deltaBytes: deltaBytes,    deltaElements: deltaElements  };}function applyOperations(ast, uint8Buffer, ops) {  ops.forEach(function (op) {    var state;    var sectionName;    switch (op.kind) {      case "update":        state = applyUpdate(ast, uint8Buffer, [op.oldNode, op.node]);        sectionName = (0, _helperWasmBytecode.getSectionForNode)(op.node);        break;      case "delete":        state = applyDelete(ast, uint8Buffer, op.node);        sectionName = (0, _helperWasmBytecode.getSectionForNode)(op.node);        break;      case "add":        state = applyAdd(ast, uint8Buffer, op.node);        sectionName = (0, _helperWasmBytecode.getSectionForNode)(op.node);        break;      default:        throw new Error("Unknown operation");    }    /**     * Resize section vec size.     * If the length of the LEB-encoded size changes, this can change     * the byte length of the section and the offset for nodes in the     * section. So we do this first before resizing section byte size     * or shifting following operations' nodes.     */    if (state.deltaElements !== 0 && sectionName !== "start") {      var oldBufferLength = state.uint8Buffer.length;      state.uint8Buffer = (0, _helperWasmSection.resizeSectionVecSize)(ast, state.uint8Buffer, sectionName, state.deltaElements); // Infer bytes added/removed by comparing buffer lengths      state.deltaBytes += state.uint8Buffer.length - oldBufferLength;    }    /**     * Resize section byte size.     * If the length of the LEB-encoded size changes, this can change     * the offset for nodes in the section. So we do this before     * shifting following operations' nodes.     */    if (state.deltaBytes !== 0 && sectionName !== "start") {      var _oldBufferLength = state.uint8Buffer.length;      state.uint8Buffer = (0, _helperWasmSection.resizeSectionByteSize)(ast, state.uint8Buffer, sectionName, state.deltaBytes); // Infer bytes added/removed by comparing buffer lengths      state.deltaBytes += state.uint8Buffer.length - _oldBufferLength;    }    /**     * Shift following operation's nodes     */    if (state.deltaBytes !== 0) {      ops.forEach(function (op) {        // We don't need to handle add ops, they are positioning independent        switch (op.kind) {          case "update":            shiftLocNodeByDelta(op.oldNode, state.deltaBytes);            break;          case "delete":            shiftLocNodeByDelta(op.node, state.deltaBytes);            break;        }      });    }    uint8Buffer = state.uint8Buffer;  });  return uint8Buffer;}
 |