| "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; | 
| } |