Index: third_party/WebKit/Source/core/streams/SimpleQueue.js |
diff --git a/third_party/WebKit/Source/core/streams/SimpleQueue.js b/third_party/WebKit/Source/core/streams/SimpleQueue.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2f6b3957afa69dd91633c617fc21c5aed320ffe8 |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/streams/SimpleQueue.js |
@@ -0,0 +1,91 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// Queue implementation used by ReadableStream and WritableStream. |
+ |
+(function(global, binding, v8) { |
+ 'use strict'; |
+ |
+ // Simple queue structure. Avoids scalability issues with using |
+ // InternalPackedArray directly by using multiple arrays in a linked list and |
+ // keeping the array size bounded. |
+ const QUEUE_MAX_ARRAY_SIZE = 16384; |
+ class SimpleQueue { |
+ constructor() { |
+ this.front = { |
+ elements: new v8.InternalPackedArray(), |
+ next: undefined, |
+ }; |
+ this.back = this.front; |
+ // The cursor is used to avoid calling InternalPackedArray.shift(). |
+ this.cursor = 0; |
+ this.size = 0; |
+ } |
+ |
+ get length() { |
+ return this.size; |
+ } |
+ |
+ push(element) { |
+ ++this.size; |
+ if (this.back.elements.length === QUEUE_MAX_ARRAY_SIZE) { |
+ const oldBack = this.back; |
+ this.back = { |
+ elements: new v8.InternalPackedArray(), |
+ next: undefined, |
+ }; |
+ oldBack.next = this.back; |
+ } |
+ this.back.elements.push(element); |
+ } |
+ |
+ shift() { |
+ // assert(this.size > 0); |
+ --this.size; |
+ if (this.front.elements.length === this.cursor) { |
+ // assert(this.cursor === QUEUE_MAX_ARRAY_SIZE); |
+ // assert(this.front.next !== undefined); |
+ this.front = this.front.next; |
+ this.cursor = 0; |
+ } |
+ const element = this.front.elements[this.cursor]; |
+ // Permit shifted element to be garbage collected. |
+ this.front.elements[this.cursor] = undefined; |
+ ++this.cursor; |
+ |
+ return element; |
+ } |
+ |
+ forEach(callback) { |
+ let i = this.cursor; |
+ let node = this.front; |
+ let elements = node.elements; |
+ while (i !== elements.length || node.next !== undefined) { |
+ if (i === elements.length) { |
+ // assert(node.next !== undefined); |
+ // assert(i === QUEUE_MAX_ARRAY_SIZE); |
+ node = node.next; |
+ elements = node.elements; |
+ i = 0; |
+ } |
+ callback(elements[i]); |
+ ++i; |
+ } |
+ } |
+ |
+ // Return the element that would be returned if shift() was called now, |
+ // without modifying the queue. |
+ peek() { |
+ // assert(this.size > 0); |
+ if (this.front.elements.length === this.cursor) { |
+ // assert(this.cursor === QUEUE_MAX_ARRAY_SIZE) |
+ // assert(this.front.next !== undefined); |
+ return this.front.next.elements[0]; |
+ } |
+ return this.front.elements[this.cursor]; |
+ } |
+ } |
+ |
+ binding.SimpleQueue = SimpleQueue; |
+}); |