Projekt

Obecné

Profil

Stáhnout (9.48 KB) Statistiky
| Větev: | Revize:
1
"use strict";
2

    
3
Object.defineProperty(exports, "__esModule", {
4
  value: true
5
});
6
exports.applyOperations = applyOperations;
7

    
8
var _wasmGen = require("@webassemblyjs/wasm-gen");
9

    
10
var _encoder = require("@webassemblyjs/wasm-gen/lib/encoder");
11

    
12
var _ast = require("@webassemblyjs/ast");
13

    
14
var _helperWasmSection = require("@webassemblyjs/helper-wasm-section");
15

    
16
var _helperBuffer = require("@webassemblyjs/helper-buffer");
17

    
18
var _helperWasmBytecode = require("@webassemblyjs/helper-wasm-bytecode");
19

    
20
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; }
21

    
22
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"); } }
23

    
24
function shiftLocNodeByDelta(node, delta) {
25
  (0, _ast.assertHasLoc)(node); // $FlowIgnore: assertHasLoc ensures that
26

    
27
  node.loc.start.column += delta; // $FlowIgnore: assertHasLoc ensures that
28

    
29
  node.loc.end.column += delta;
30
}
31

    
32
function applyUpdate(ast, uint8Buffer, _ref) {
33
  var _ref2 = _slicedToArray(_ref, 2),
34
      oldNode = _ref2[0],
35
      newNode = _ref2[1];
36

    
37
  var deltaElements = 0;
38
  (0, _ast.assertHasLoc)(oldNode);
39
  var sectionName = (0, _helperWasmBytecode.getSectionForNode)(newNode);
40
  var replacementByteArray = (0, _wasmGen.encodeNode)(newNode);
41
  /**
42
   * Replace new node as bytes
43
   */
44

    
45
  uint8Buffer = (0, _helperBuffer.overrideBytesInBuffer)(uint8Buffer, // $FlowIgnore: assertHasLoc ensures that
46
  oldNode.loc.start.column, // $FlowIgnore: assertHasLoc ensures that
47
  oldNode.loc.end.column, replacementByteArray);
48
  /**
49
   * Update function body size if needed
50
   */
51

    
52
  if (sectionName === "code") {
53
    // Find the parent func
54
    (0, _ast.traverse)(ast, {
55
      Func: function Func(_ref3) {
56
        var node = _ref3.node;
57
        var funcHasThisIntr = node.body.find(function (n) {
58
          return n === newNode;
59
        }) !== undefined; // Update func's body size if needed
60

    
61
        if (funcHasThisIntr === true) {
62
          // These are the old functions locations informations
63
          (0, _ast.assertHasLoc)(node);
64
          var oldNodeSize = (0, _wasmGen.encodeNode)(oldNode).length;
65
          var bodySizeDeltaBytes = replacementByteArray.length - oldNodeSize;
66

    
67
          if (bodySizeDeltaBytes !== 0) {
68
            var newValue = node.metadata.bodySize + bodySizeDeltaBytes;
69
            var newByteArray = (0, _encoder.encodeU32)(newValue); // function body size byte
70
            // FIXME(sven): only handles one byte u32
71

    
72
            var start = node.loc.start.column;
73
            var end = start + 1;
74
            uint8Buffer = (0, _helperBuffer.overrideBytesInBuffer)(uint8Buffer, start, end, newByteArray);
75
          }
76
        }
77
      }
78
    });
79
  }
80
  /**
81
   * Update section size
82
   */
83

    
84

    
85
  var deltaBytes = replacementByteArray.length - ( // $FlowIgnore: assertHasLoc ensures that
86
  oldNode.loc.end.column - oldNode.loc.start.column); // Init location informations
87

    
88
  newNode.loc = {
89
    start: {
90
      line: -1,
91
      column: -1
92
    },
93
    end: {
94
      line: -1,
95
      column: -1
96
    }
97
  }; // Update new node end position
98
  // $FlowIgnore: assertHasLoc ensures that
99

    
100
  newNode.loc.start.column = oldNode.loc.start.column; // $FlowIgnore: assertHasLoc ensures that
101

    
102
  newNode.loc.end.column = // $FlowIgnore: assertHasLoc ensures that
103
  oldNode.loc.start.column + replacementByteArray.length;
104
  return {
105
    uint8Buffer: uint8Buffer,
106
    deltaBytes: deltaBytes,
107
    deltaElements: deltaElements
108
  };
109
}
110

    
111
function applyDelete(ast, uint8Buffer, node) {
112
  var deltaElements = -1; // since we removed an element
113

    
114
  (0, _ast.assertHasLoc)(node);
115
  var sectionName = (0, _helperWasmBytecode.getSectionForNode)(node);
116

    
117
  if (sectionName === "start") {
118
    var sectionMetadata = (0, _ast.getSectionMetadata)(ast, "start");
119
    /**
120
     * The start section only contains one element,
121
     * we need to remove the whole section
122
     */
123

    
124
    uint8Buffer = (0, _helperWasmSection.removeSections)(ast, uint8Buffer, "start");
125

    
126
    var _deltaBytes = -(sectionMetadata.size.value + 1);
127
    /* section id */
128

    
129

    
130
    return {
131
      uint8Buffer: uint8Buffer,
132
      deltaBytes: _deltaBytes,
133
      deltaElements: deltaElements
134
    };
135
  } // replacement is nothing
136

    
137

    
138
  var replacement = [];
139
  uint8Buffer = (0, _helperBuffer.overrideBytesInBuffer)(uint8Buffer, // $FlowIgnore: assertHasLoc ensures that
140
  node.loc.start.column, // $FlowIgnore: assertHasLoc ensures that
141
  node.loc.end.column, replacement);
142
  /**
143
   * Update section
144
   */
145
  // $FlowIgnore: assertHasLoc ensures that
146

    
147
  var deltaBytes = -(node.loc.end.column - node.loc.start.column);
148
  return {
149
    uint8Buffer: uint8Buffer,
150
    deltaBytes: deltaBytes,
151
    deltaElements: deltaElements
152
  };
153
}
154

    
155
function applyAdd(ast, uint8Buffer, node) {
156
  var deltaElements = +1; // since we added an element
157

    
158
  var sectionName = (0, _helperWasmBytecode.getSectionForNode)(node);
159
  var sectionMetadata = (0, _ast.getSectionMetadata)(ast, sectionName); // Section doesn't exists, we create an empty one
160

    
161
  if (typeof sectionMetadata === "undefined") {
162
    var res = (0, _helperWasmSection.createEmptySection)(ast, uint8Buffer, sectionName);
163
    uint8Buffer = res.uint8Buffer;
164
    sectionMetadata = res.sectionMetadata;
165
  }
166
  /**
167
   * check that the expressions were ended
168
   */
169

    
170

    
171
  if ((0, _ast.isFunc)(node)) {
172
    // $FlowIgnore
173
    var body = node.body;
174

    
175
    if (body.length === 0 || body[body.length - 1].id !== "end") {
176
      throw new Error("expressions must be ended");
177
    }
178
  }
179

    
180
  if ((0, _ast.isGlobal)(node)) {
181
    // $FlowIgnore
182
    var body = node.init;
183

    
184
    if (body.length === 0 || body[body.length - 1].id !== "end") {
185
      throw new Error("expressions must be ended");
186
    }
187
  }
188
  /**
189
   * Add nodes
190
   */
191

    
192

    
193
  var newByteArray = (0, _wasmGen.encodeNode)(node); // The size of the section doesn't include the storage of the size itself
194
  // we need to manually add it here
195

    
196
  var start = (0, _ast.getEndOfSection)(sectionMetadata);
197
  var end = start;
198
  /**
199
   * Update section
200
   */
201

    
202
  var deltaBytes = newByteArray.length;
203
  uint8Buffer = (0, _helperBuffer.overrideBytesInBuffer)(uint8Buffer, start, end, newByteArray);
204
  node.loc = {
205
    start: {
206
      line: -1,
207
      column: start
208
    },
209
    end: {
210
      line: -1,
211
      column: start + deltaBytes
212
    }
213
  }; // for func add the additional metadata in the AST
214

    
215
  if (node.type === "Func") {
216
    // the size is the first byte
217
    // FIXME(sven): handle LEB128 correctly here
218
    var bodySize = newByteArray[0];
219
    node.metadata = {
220
      bodySize: bodySize
221
    };
222
  }
223

    
224
  if (node.type !== "IndexInFuncSection") {
225
    (0, _ast.orderedInsertNode)(ast.body[0], node);
226
  }
227

    
228
  return {
229
    uint8Buffer: uint8Buffer,
230
    deltaBytes: deltaBytes,
231
    deltaElements: deltaElements
232
  };
233
}
234

    
235
function applyOperations(ast, uint8Buffer, ops) {
236
  ops.forEach(function (op) {
237
    var state;
238
    var sectionName;
239

    
240
    switch (op.kind) {
241
      case "update":
242
        state = applyUpdate(ast, uint8Buffer, [op.oldNode, op.node]);
243
        sectionName = (0, _helperWasmBytecode.getSectionForNode)(op.node);
244
        break;
245

    
246
      case "delete":
247
        state = applyDelete(ast, uint8Buffer, op.node);
248
        sectionName = (0, _helperWasmBytecode.getSectionForNode)(op.node);
249
        break;
250

    
251
      case "add":
252
        state = applyAdd(ast, uint8Buffer, op.node);
253
        sectionName = (0, _helperWasmBytecode.getSectionForNode)(op.node);
254
        break;
255

    
256
      default:
257
        throw new Error("Unknown operation");
258
    }
259
    /**
260
     * Resize section vec size.
261
     * If the length of the LEB-encoded size changes, this can change
262
     * the byte length of the section and the offset for nodes in the
263
     * section. So we do this first before resizing section byte size
264
     * or shifting following operations' nodes.
265
     */
266

    
267

    
268
    if (state.deltaElements !== 0 && sectionName !== "start") {
269
      var oldBufferLength = state.uint8Buffer.length;
270
      state.uint8Buffer = (0, _helperWasmSection.resizeSectionVecSize)(ast, state.uint8Buffer, sectionName, state.deltaElements); // Infer bytes added/removed by comparing buffer lengths
271

    
272
      state.deltaBytes += state.uint8Buffer.length - oldBufferLength;
273
    }
274
    /**
275
     * Resize section byte size.
276
     * If the length of the LEB-encoded size changes, this can change
277
     * the offset for nodes in the section. So we do this before
278
     * shifting following operations' nodes.
279
     */
280

    
281

    
282
    if (state.deltaBytes !== 0 && sectionName !== "start") {
283
      var _oldBufferLength = state.uint8Buffer.length;
284
      state.uint8Buffer = (0, _helperWasmSection.resizeSectionByteSize)(ast, state.uint8Buffer, sectionName, state.deltaBytes); // Infer bytes added/removed by comparing buffer lengths
285

    
286
      state.deltaBytes += state.uint8Buffer.length - _oldBufferLength;
287
    }
288
    /**
289
     * Shift following operation's nodes
290
     */
291

    
292

    
293
    if (state.deltaBytes !== 0) {
294
      ops.forEach(function (op) {
295
        // We don't need to handle add ops, they are positioning independent
296
        switch (op.kind) {
297
          case "update":
298
            shiftLocNodeByDelta(op.oldNode, state.deltaBytes);
299
            break;
300

    
301
          case "delete":
302
            shiftLocNodeByDelta(op.node, state.deltaBytes);
303
            break;
304
        }
305
      });
306
    }
307

    
308
    uint8Buffer = state.uint8Buffer;
309
  });
310
  return uint8Buffer;
311
}
(1-1/2)