1 | const hasOwnProperty = require('has-own-prop')
|
2 | const {isArray} = require('core-util-is')
|
3 |
|
4 | const {
|
5 | SYMBOL_PREFIXES,
|
6 |
|
7 | UNDEFINED,
|
8 |
|
9 | symbol,
|
10 | define,
|
11 | copy_comments
|
12 | } = require('./common')
|
13 |
|
14 |
|
15 | const swap_comments = (array, from, to) => {
|
16 | if (from === to) {
|
17 | return
|
18 | }
|
19 |
|
20 | SYMBOL_PREFIXES.forEach(prefix => {
|
21 | const target_prop = symbol(prefix, to)
|
22 | if (!hasOwnProperty(array, target_prop)) {
|
23 | copy_comments(array, array, to, from, prefix)
|
24 | return
|
25 | }
|
26 |
|
27 | const comments = array[target_prop]
|
28 | copy_comments(array, array, to, from, prefix)
|
29 | define(array, symbol(prefix, from), comments)
|
30 | })
|
31 | }
|
32 |
|
33 | const reverse_comments = array => {
|
34 | const {length} = array
|
35 | let i = 0
|
36 | const max = length / 2
|
37 |
|
38 | for (; i < max; i ++) {
|
39 | swap_comments(array, i, length - i - 1)
|
40 | }
|
41 | }
|
42 |
|
43 | const move_comment = (target, source, i, offset, remove) => {
|
44 | SYMBOL_PREFIXES.forEach(prefix => {
|
45 | copy_comments(target, source, i + offset, i, prefix, remove)
|
46 | })
|
47 | }
|
48 |
|
49 | const move_comments = (
|
50 |
|
51 | target,
|
52 |
|
53 | source,
|
54 |
|
55 | start,
|
56 |
|
57 | count,
|
58 |
|
59 | offset,
|
60 |
|
61 | remove
|
62 | ) => {
|
63 | if (offset > 0) {
|
64 | let i = count
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 | while (i -- > 0) {
|
73 | move_comment(target, source, start + i, offset, remove && i < offset)
|
74 | }
|
75 | return
|
76 | }
|
77 |
|
78 | let i = 0
|
79 | const min_remove = count + offset
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 | while (i < count) {
|
87 | const ii = i ++
|
88 | move_comment(target, source, start + ii, offset, remove && i >= min_remove)
|
89 | }
|
90 | }
|
91 |
|
92 | class CommentArray extends Array {
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 | splice (...args) {
|
100 | const {length} = this
|
101 | const ret = super.splice(...args)
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 | let [begin, deleteCount, ...items] = args
|
114 |
|
115 | if (begin < 0) {
|
116 | begin += length
|
117 | }
|
118 |
|
119 | if (arguments.length === 1) {
|
120 | deleteCount = length - begin
|
121 | } else {
|
122 | deleteCount = Math.min(length - begin, deleteCount)
|
123 | }
|
124 |
|
125 | const {
|
126 | length: item_length
|
127 | } = items
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 | const offset = item_length - deleteCount
|
136 | const start = begin + deleteCount
|
137 | const count = length - start
|
138 |
|
139 | move_comments(this, this, start, count, offset, true)
|
140 |
|
141 | return ret
|
142 | }
|
143 |
|
144 | slice (...args) {
|
145 | const {length} = this
|
146 | const array = super.slice(...args)
|
147 | if (!array.length) {
|
148 | return new CommentArray()
|
149 | }
|
150 |
|
151 | let [begin, before] = args
|
152 |
|
153 |
|
154 |
|
155 | if (before === UNDEFINED) {
|
156 | before = length
|
157 | } else if (before < 0) {
|
158 | before += length
|
159 | }
|
160 |
|
161 | if (begin < 0) {
|
162 | begin += length
|
163 | } else if (begin === UNDEFINED) {
|
164 | begin = 0
|
165 | }
|
166 |
|
167 | move_comments(array, this, begin, before - begin, - begin)
|
168 |
|
169 | return array
|
170 | }
|
171 |
|
172 | unshift (...items) {
|
173 | const {length} = this
|
174 | const ret = super.unshift(...items)
|
175 | const {
|
176 | length: items_length
|
177 | } = items
|
178 |
|
179 | if (items_length > 0) {
|
180 | move_comments(this, this, 0, length, items_length, true)
|
181 | }
|
182 |
|
183 | return ret
|
184 | }
|
185 |
|
186 | shift () {
|
187 | const ret = super.shift()
|
188 | const {length} = this
|
189 |
|
190 | move_comments(this, this, 1, length, - 1, true)
|
191 |
|
192 | return ret
|
193 | }
|
194 |
|
195 | reverse () {
|
196 | super.reverse()
|
197 |
|
198 | reverse_comments(this)
|
199 |
|
200 | return this
|
201 | }
|
202 |
|
203 | pop () {
|
204 | const ret = super.pop()
|
205 |
|
206 |
|
207 | const {length} = this
|
208 | SYMBOL_PREFIXES.forEach(prefix => {
|
209 | const prop = symbol(prefix, length)
|
210 | delete this[prop]
|
211 | })
|
212 |
|
213 | return ret
|
214 | }
|
215 |
|
216 | concat (...items) {
|
217 | let {length} = this
|
218 | const ret = super.concat(...items)
|
219 |
|
220 | if (!items.length) {
|
221 | return ret
|
222 | }
|
223 |
|
224 | items.forEach(item => {
|
225 | const prev = length
|
226 | length += isArray(item)
|
227 | ? item.length
|
228 | : 1
|
229 |
|
230 | if (!(item instanceof CommentArray)) {
|
231 | return
|
232 | }
|
233 |
|
234 | move_comments(ret, item, 0, item.length, prev)
|
235 | })
|
236 |
|
237 | return ret
|
238 | }
|
239 | }
|
240 |
|
241 | module.exports = {
|
242 | CommentArray
|
243 | }
|