UNPKG

11.3 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright Google LLC All Rights Reserved.
5 *
6 * Use of this source code is governed by an MIT-style license that can be
7 * found in the LICENSE file at https://angular.io/license
8 */
9var __importDefault = (this && this.__importDefault) || function (mod) {
10 return (mod && mod.__esModule) ? mod : { "default": mod };
11};
12Object.defineProperty(exports, "__esModule", { value: true });
13exports.UpdateBuffer2 = exports.UpdateBuffer = exports.UpdateBufferBase = exports.Chunk = exports.ContentCannotBeRemovedException = exports.IndexOutOfBoundException = void 0;
14const core_1 = require("@angular-devkit/core");
15const magic_string_1 = __importDefault(require("magic-string"));
16const environment_options_1 = require("./environment-options");
17const linked_list_1 = require("./linked-list");
18class IndexOutOfBoundException extends core_1.BaseException {
19 constructor(index, min, max = Infinity) {
20 super(`Index ${index} outside of range [${min}, ${max}].`);
21 }
22}
23exports.IndexOutOfBoundException = IndexOutOfBoundException;
24/** @deprecated Since v13.0 */
25class ContentCannotBeRemovedException extends core_1.BaseException {
26 constructor() {
27 super(`User tried to remove content that was marked essential.`);
28 }
29}
30exports.ContentCannotBeRemovedException = ContentCannotBeRemovedException;
31/**
32 * A Chunk description, including left/right content that has been inserted.
33 * If _left/_right is null, this means that content was deleted. If the _content is null,
34 * it means the content itself was deleted.
35 *
36 * @see UpdateBuffer
37 * @deprecated Since v13.0
38 */
39class Chunk {
40 constructor(start, end, originalContent) {
41 this.start = start;
42 this.end = end;
43 this.originalContent = originalContent;
44 this._left = Buffer.alloc(0);
45 this._right = Buffer.alloc(0);
46 this._assertLeft = false;
47 this._assertRight = false;
48 this.next = null;
49 this._content = originalContent.slice(start, end);
50 }
51 get length() {
52 return ((this._left ? this._left.length : 0) +
53 (this._content ? this._content.length : 0) +
54 (this._right ? this._right.length : 0));
55 }
56 toString(encoding = 'utf-8') {
57 return ((this._left ? this._left.toString(encoding) : '') +
58 (this._content ? this._content.toString(encoding) : '') +
59 (this._right ? this._right.toString(encoding) : ''));
60 }
61 slice(start) {
62 if (start < this.start || start > this.end) {
63 throw new IndexOutOfBoundException(start, this.start, this.end);
64 }
65 // Update _content to the new indices.
66 const newChunk = new Chunk(start, this.end, this.originalContent);
67 // If this chunk has _content, reslice the original _content. We move the _right so we are not
68 // losing any data here. If this chunk has been deleted, the next chunk should also be deleted.
69 if (this._content) {
70 this._content = this.originalContent.slice(this.start, start);
71 }
72 else {
73 newChunk._content = this._content;
74 if (this._right === null) {
75 newChunk._left = null;
76 }
77 }
78 this.end = start;
79 // Move _right to the new chunk.
80 newChunk._right = this._right;
81 this._right = this._right && Buffer.alloc(0);
82 // Update essentials.
83 if (this._assertRight) {
84 newChunk._assertRight = true;
85 this._assertRight = false;
86 }
87 // Update the linked list.
88 newChunk.next = this.next;
89 this.next = newChunk;
90 return newChunk;
91 }
92 append(buffer, essential) {
93 if (!this._right) {
94 if (essential) {
95 throw new ContentCannotBeRemovedException();
96 }
97 return;
98 }
99 const outro = this._right;
100 this._right = Buffer.alloc(outro.length + buffer.length);
101 outro.copy(this._right, 0);
102 buffer.copy(this._right, outro.length);
103 if (essential) {
104 this._assertRight = true;
105 }
106 }
107 prepend(buffer, essential) {
108 if (!this._left) {
109 if (essential) {
110 throw new ContentCannotBeRemovedException();
111 }
112 return;
113 }
114 const intro = this._left;
115 this._left = Buffer.alloc(intro.length + buffer.length);
116 intro.copy(this._left, 0);
117 buffer.copy(this._left, intro.length);
118 if (essential) {
119 this._assertLeft = true;
120 }
121 }
122 assert(left, _content, right) {
123 if (left && this._assertLeft) {
124 throw new ContentCannotBeRemovedException();
125 }
126 if (right && this._assertRight) {
127 throw new ContentCannotBeRemovedException();
128 }
129 }
130 remove(left, content, right) {
131 if (left) {
132 if (this._assertLeft) {
133 throw new ContentCannotBeRemovedException();
134 }
135 this._left = null;
136 }
137 if (content) {
138 this._content = null;
139 }
140 if (right) {
141 if (this._assertRight) {
142 throw new ContentCannotBeRemovedException();
143 }
144 this._right = null;
145 }
146 }
147 copy(target, start) {
148 if (this._left) {
149 this._left.copy(target, start);
150 start += this._left.length;
151 }
152 if (this._content) {
153 this._content.copy(target, start);
154 start += this._content.length;
155 }
156 if (this._right) {
157 this._right.copy(target, start);
158 start += this._right.length;
159 }
160 return start;
161 }
162}
163exports.Chunk = Chunk;
164/**
165 * Base class for an update buffer implementation that allows buffers to be inserted to the _right
166 * or _left, or deleted, while keeping indices to the original buffer.
167 */
168class UpdateBufferBase {
169 constructor(_originalContent) {
170 this._originalContent = _originalContent;
171 }
172 /**
173 * Creates an UpdateBufferBase instance. Depending on the NG_UPDATE_BUFFER_V2
174 * environment variable, will either create an UpdateBuffer or an UpdateBuffer2
175 * instance.
176 *
177 * See: https://github.com/angular/angular-cli/issues/21110
178 *
179 * @param originalContent The original content of the update buffer instance.
180 * @returns An UpdateBufferBase instance.
181 */
182 static create(originalContent) {
183 return environment_options_1.updateBufferV2Enabled
184 ? new UpdateBuffer2(originalContent)
185 : new UpdateBuffer(originalContent);
186 }
187}
188exports.UpdateBufferBase = UpdateBufferBase;
189/**
190 * An utility class that allows buffers to be inserted to the _right or _left, or deleted, while
191 * keeping indices to the original buffer.
192 *
193 * The constructor takes an original buffer, and keeps it into a linked list of chunks, smaller
194 * buffers that keep track of _content inserted to the _right or _left of it.
195 *
196 * Since the Node Buffer structure is non-destructive when slicing, we try to use slicing to create
197 * new chunks, and always keep chunks pointing to the original content.
198 *
199 * @deprecated Since v13.0
200 */
201class UpdateBuffer extends UpdateBufferBase {
202 constructor(originalContent) {
203 super(originalContent);
204 this._linkedList = new linked_list_1.LinkedList(new Chunk(0, originalContent.length, originalContent));
205 }
206 _assertIndex(index) {
207 if (index < 0 || index > this._originalContent.length) {
208 throw new IndexOutOfBoundException(index, 0, this._originalContent.length);
209 }
210 }
211 _slice(start) {
212 let index;
213 if (start >= this._originalContent.length) {
214 index = start;
215 }
216 else if (start < 0) {
217 index = this._originalContent.length + start;
218 }
219 else {
220 index = this._getTextPosition(start);
221 }
222 this._assertIndex(index);
223 // Find the chunk by going through the list.
224 const h = this._linkedList.find((chunk) => index <= chunk.end);
225 if (!h) {
226 throw Error('Chunk cannot be found.');
227 }
228 if (index == h.end && h.next !== null) {
229 return [h, h.next];
230 }
231 return [h, h.slice(index)];
232 }
233 /**
234 * Gets the position in the content based on the position in the string.
235 * Some characters might be wider than one byte, thus we have to determine the position using
236 * string functions.
237 */
238 _getTextPosition(index) {
239 return Buffer.from(this._originalContent.toString().substring(0, index)).length;
240 }
241 get length() {
242 return this._linkedList.reduce((acc, chunk) => acc + chunk.length, 0);
243 }
244 get original() {
245 return this._originalContent;
246 }
247 toString(encoding = 'utf-8') {
248 return this._linkedList.reduce((acc, chunk) => acc + chunk.toString(encoding), '');
249 }
250 generate() {
251 const result = Buffer.allocUnsafe(this.length);
252 let i = 0;
253 this._linkedList.forEach((chunk) => {
254 chunk.copy(result, i);
255 i += chunk.length;
256 });
257 return result;
258 }
259 insertLeft(index, content, assert = false) {
260 this._slice(index)[0].append(content, assert);
261 }
262 insertRight(index, content, assert = false) {
263 this._slice(index)[1].prepend(content, assert);
264 }
265 remove(index, length) {
266 if (length === 0) {
267 return;
268 }
269 const end = index + length;
270 const first = this._slice(index)[1];
271 const last = this._slice(end)[1];
272 let curr;
273 for (curr = first; curr && curr !== last; curr = curr.next) {
274 curr.assert(curr !== first, curr !== last, curr === first);
275 }
276 for (curr = first; curr && curr !== last; curr = curr.next) {
277 curr.remove(curr !== first, curr !== last, curr === first);
278 }
279 if (curr) {
280 curr.remove(true, false, false);
281 }
282 }
283}
284exports.UpdateBuffer = UpdateBuffer;
285/**
286 * An utility class that allows buffers to be inserted to the _right or _left, or deleted, while
287 * keeping indices to the original buffer.
288 */
289class UpdateBuffer2 extends UpdateBufferBase {
290 constructor() {
291 super(...arguments);
292 this._mutatableContent = new magic_string_1.default(this._originalContent.toString());
293 }
294 _assertIndex(index) {
295 if (index < 0 || index > this._originalContent.length) {
296 throw new IndexOutOfBoundException(index, 0, this._originalContent.length);
297 }
298 }
299 get length() {
300 return this._mutatableContent.length();
301 }
302 get original() {
303 return this._originalContent;
304 }
305 toString() {
306 return this._mutatableContent.toString();
307 }
308 generate() {
309 return Buffer.from(this.toString());
310 }
311 insertLeft(index, content) {
312 this._assertIndex(index);
313 this._mutatableContent.appendLeft(index, content.toString());
314 }
315 insertRight(index, content) {
316 this._assertIndex(index);
317 this._mutatableContent.appendRight(index, content.toString());
318 }
319 remove(index, length) {
320 this._assertIndex(index);
321 this._mutatableContent.remove(index, index + length);
322 }
323}
324exports.UpdateBuffer2 = UpdateBuffer2;