Index: lib/typedObjects/arrayTypes.js |
diff --git a/lib/typedObjects/arrayTypes.js b/lib/typedObjects/arrayTypes.js |
index 03e48ba0addada242f0f263ecc28b7c8f990e8fe..d08cc0cd17bae0e8092b8b2f5f3ad10869b1583b 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,23 @@ 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 |
+ if (this.hasOwnProperty("length")) |
+ delete this.length; |
+ |
+ this.length = 0; |
+ this.size = 0; |
+ } |
}; |
function createGetter(elementGetter, elementShift) |
@@ -212,6 +227,50 @@ function pop() |
return result; |
} |
+function createSlicer(elementShift) |
+{ |
+ 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: 0, 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 +384,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); |