| Index: lib/typedObjects/arrayTypes.js |
| diff --git a/lib/typedObjects/arrayTypes.js b/lib/typedObjects/arrayTypes.js |
| index 03e48ba0addada242f0f263ecc28b7c8f990e8fe..051d294a1c4db2d4c2193deb77fe0b3102dd15af 100644 |
| --- a/lib/typedObjects/arrayTypes.js |
| +++ b/lib/typedObjects/arrayTypes.js |
| @@ -17,7 +17,7 @@ |
| "use strict"; |
| -let {ilog2, nextPow2, alloc, dealloc, addBuffer, removeBuffer} = require("typedObjects/utils"); |
| +let {ilog2, nextPow2, alloc, fixedPropertyDescriptor, dealloc, addBuffer, removeBuffer} = require("typedObjects/utils"); |
| function defaultArrayConstructor() |
| { |
| @@ -26,8 +26,22 @@ function defaultArrayConstructor() |
| function defaultArrayDestructor() |
| { |
| - this.length = 0; |
| - this.size = 0; |
| + if (this._copy) |
| + { |
| + // Carefully zero length + size if this is a slice of an array |
| + Object.defineProperties(this, { |
| + length: fixedPropertyDescriptor(0), |
| + size: fixedPropertyDescriptor(0) |
| + }); |
| + } |
| + else |
| + { |
| + // Remove read-only length property for previously sliced arrays |
| + delete this.length; |
| + |
| + this.length = 0; |
| + this.size = 0; |
| + } |
| }; |
| function createGetter(elementGetter, elementShift) |
| @@ -212,6 +226,52 @@ function pop() |
| return result; |
| } |
| +function createSlicer(elementShift) |
| +{ |
| + let {STATE_UNINITIALIZED} = require("typedObjects/objectTypes"); |
| + |
| + return function slice(start, end) |
| + { |
| + start = start | 0; |
| + end = end | 0; |
| + |
| + if (start < 0) |
| + start = Math.max(0, this.length + start); |
| + else |
| + start = Math.min(start, this.length); |
| + |
| + if (end > 0) |
| + end = Math.min(0, end - this.length); |
| + else |
| + end = Math.max(end, -1 * this.length); |
| + |
| + Object.defineProperties(this, { |
| + length: {value: this.length, configurable: true} |
| + }); |
| + this.retain(); |
| + |
| + let result = Object.create(this, { |
| + arrayByteOffset: fixedPropertyDescriptor( |
| + this.arrayByteOffset + start << elementShift |
| + ), |
| + length: {value: this.length - start + end, configurable: true}, |
| + _refCount: {value: 1, writable: true}, |
| + _copy: fixedPropertyDescriptor(true), |
| + _state: {value: STATE_UNINITIALIZED, writable: true} |
| + }); |
| + |
| + // TODO |
| + // - A sliced array will have a read-only length even if all slices are |
| + // released. We could fix this by keeping a count of slices, but is it |
| + // worth it? |
| + // - A slice of an array still keeps a reference to the array in it's |
| + // __proto__ property after it's released. (We can't just replace it |
| + // with null as modifying an object's prototype is apparently very slow.) |
| + |
| + return result; |
| + }; |
| +} |
| + |
| function splice(index, count) |
| { |
| index = index | 0; |
| @@ -325,6 +385,7 @@ function createArrayType(elementType, typeDescriptor, meta) |
| typeDescriptor.shift = shift; |
| let elementShift = ilog2(elementType.referenceLength | 0); |
| + typeDescriptor.slice = createSlicer(elementShift); |
| typeDescriptor.get = createGetter(elementGetter, elementShift); |
| typeDescriptor.set = createSetter(elementSetter, elementShift); |