|
1 | 1 | 'use strict';
|
2 | 2 |
|
3 | 3 | const util = require('util');
|
4 |
| -const acorn = require('acorn'); |
| 4 | +const { parse_dammit: parseDammit } = require('acorn/dist/acorn_loose'); |
5 | 5 | const IO = require('./io');
|
6 | 6 | const highlight = require('./highlight');
|
7 | 7 | const { processTopLevelAwait } = require('./await');
|
@@ -47,14 +47,6 @@ function wrapObjectLiteralExpressionIfNeeded(code) {
|
47 | 47 | }
|
48 | 48 | }
|
49 | 49 |
|
50 |
| -function isCallExpression(code) { |
51 |
| - try { |
52 |
| - return acorn.parse(code).body[0].expression.type === 'CallExpression'; |
53 |
| - } catch { |
54 |
| - return false; |
55 |
| - } |
56 |
| -} |
57 |
| - |
58 | 50 | async function collectGlobalNames() {
|
59 | 51 | const keys = Object.getOwnPropertyNames(global);
|
60 | 52 | try {
|
@@ -170,115 +162,98 @@ Prototype REPL - https://github.com/nodejs/repl`,
|
170 | 162 | }
|
171 | 163 |
|
172 | 164 | async onAutocomplete(buffer) {
|
| 165 | + if (buffer.length === 0) { |
| 166 | + return collectGlobalNames(); |
| 167 | + } |
| 168 | + |
| 169 | + const statement = parseDammit(buffer).body[0]; |
| 170 | + if (statement.type !== 'ExpressionStatement') { |
| 171 | + return undefined; |
| 172 | + } |
| 173 | + const { expression } = statement; |
| 174 | + |
173 | 175 | let keys;
|
174 | 176 | let filter;
|
175 |
| - if (buffer.length === 0) { |
| 177 | + if (expression.type === 'Identifier') { |
176 | 178 | keys = await collectGlobalNames();
|
177 |
| - } else { |
178 |
| - let expr; |
179 |
| - let computed = false; |
180 |
| - let leadingQuote = false; |
| 179 | + filter = expression.name; |
| 180 | + } |
181 | 181 |
|
182 |
| - let index = buffer.lastIndexOf('.'); |
183 |
| - if (index !== -1) { |
184 |
| - expr = buffer.slice(0, index); |
185 |
| - filter = buffer.slice(index + 1, buffer.length).trim(); |
| 182 | + if (expression.type === 'MemberExpression') { |
| 183 | + const expr = buffer.slice(expression.object.start, expression.object.end); |
| 184 | + let leadingQuote = false; |
| 185 | + if (expression.computed && expression.property.type === 'Literal') { |
| 186 | + filter = expression.property.value; |
| 187 | + leadingQuote = expression.property.raw.startsWith('\''); |
| 188 | + } else if (!expression.computed && expression.property.type === 'Identifier') { |
| 189 | + filter = expression.property.name === '✖' ? undefined : expression.property.name; |
186 | 190 | }
|
187 | 191 |
|
188 |
| - if (!expr) { |
189 |
| - index = buffer.lastIndexOf('[\''); |
190 |
| - if (index !== -1) { |
191 |
| - expr = buffer.slice(0, index); |
192 |
| - filter = buffer.slice(index + 2, buffer.length); |
193 |
| - computed = true; |
194 |
| - leadingQuote = true; |
195 |
| - } |
| 192 | + const evaluateResult = await this.eval(expr, false, true); |
| 193 | + if (evaluateResult.exceptionDetails) { |
| 194 | + return undefined; |
196 | 195 | }
|
197 | 196 |
|
198 |
| - if (!expr) { |
199 |
| - index = buffer.lastIndexOf('['); |
200 |
| - if (index !== -1) { |
201 |
| - expr = buffer.slice(0, index); |
202 |
| - filter = buffer.slice(index + 1, buffer.length); |
203 |
| - computed = true; |
204 |
| - } |
205 |
| - } |
| 197 | + const own = []; |
| 198 | + const inherited = []; |
| 199 | + (await Runtime.getProperties({ |
| 200 | + objectId: evaluateResult.result.objectId, |
| 201 | + generatePreview: true, |
| 202 | + })) |
| 203 | + .result |
| 204 | + .filter(({ symbol }) => !symbol) |
| 205 | + .forEach(({ isOwn, name }) => { |
| 206 | + if (isOwn) { |
| 207 | + own.push(name); |
| 208 | + } else { |
| 209 | + inherited.push(name); |
| 210 | + } |
| 211 | + }); |
206 | 212 |
|
207 |
| - if (isCallExpression(filter)) { |
208 |
| - expr = undefined; |
209 |
| - filter = undefined; |
210 |
| - } |
| 213 | + keys = [...own, ...inherited]; |
211 | 214 |
|
212 |
| - if (expr) { |
213 |
| - const evaluateResult = await this.eval(expr, false, true); |
214 |
| - if (evaluateResult.exceptionDetails) { |
| 215 | + if (keys.includes(filter)) { |
| 216 | + const { result, exceptionDetails } = |
| 217 | + await this.eval(wrapObjectLiteralExpressionIfNeeded(buffer), false, true); |
| 218 | + if (exceptionDetails) { |
215 | 219 | return undefined;
|
216 | 220 | }
|
| 221 | + return ` // ${await oneLineInspect(result)}`; |
| 222 | + } |
217 | 223 |
|
218 |
| - const own = []; |
219 |
| - const inherited = []; |
220 |
| - |
221 |
| - (await Runtime.getProperties({ |
222 |
| - objectId: evaluateResult.result.objectId, |
223 |
| - generatePreview: true, |
224 |
| - })) |
225 |
| - .result |
226 |
| - .filter(({ symbol }) => !symbol) |
227 |
| - .forEach(({ isOwn, name }) => { |
228 |
| - if (isOwn) { |
229 |
| - own.push(name); |
230 |
| - } else { |
231 |
| - inherited.push(name); |
232 |
| - } |
233 |
| - }); |
234 |
| - const k = [...own, ...inherited]; |
235 |
| - |
236 |
| - if (computed) { |
237 |
| - keys = k.map((key) => { |
238 |
| - let r; |
239 |
| - if (!leadingQuote && `${+key}` === key) { |
240 |
| - r = `${key}]`; |
241 |
| - } else { |
242 |
| - r = `${strEscape(key)}]`; |
243 |
| - } |
| 224 | + if (expression.computed) { |
| 225 | + keys = keys.map((key) => { |
| 226 | + let r; |
| 227 | + if (!leadingQuote && `${+key}` === key) { |
| 228 | + r = key; |
| 229 | + } else { |
| 230 | + r = strEscape(key); |
244 | 231 | if (leadingQuote) {
|
245 |
| - return r.slice(1); |
| 232 | + r = r.slice(1); |
246 | 233 | }
|
247 |
| - return r; |
248 |
| - }); |
249 |
| - } else { |
250 |
| - keys = k.filter(isIdentifier); |
251 |
| - } |
| 234 | + } |
| 235 | + return `${r}]`; |
| 236 | + }); |
252 | 237 | } else {
|
253 |
| - const evaluateResult = await this.eval( |
254 |
| - wrapObjectLiteralExpressionIfNeeded(buffer), false, true, |
255 |
| - ); |
256 |
| - if (evaluateResult.exceptionDetails) { |
257 |
| - return undefined; |
258 |
| - } |
259 |
| - return ` // ${await oneLineInspect(evaluateResult.result)}`; |
| 238 | + keys = keys.filter(isIdentifier); |
260 | 239 | }
|
261 | 240 | }
|
262 | 241 |
|
263 | 242 | if (keys) {
|
264 | 243 | if (filter) {
|
265 |
| - if (keys.includes(filter)) { |
266 |
| - const evaluateResult = await this.eval( |
267 |
| - wrapObjectLiteralExpressionIfNeeded(buffer), false, true, |
268 |
| - ); |
269 |
| - if (evaluateResult.exceptionDetails) { |
270 |
| - return undefined; |
271 |
| - } |
272 |
| - return ` // ${await oneLineInspect(evaluateResult.result)}`; |
273 |
| - } |
274 |
| - |
275 | 244 | return keys
|
276 | 245 | .filter((k) => k.startsWith(filter))
|
277 | 246 | .map((k) => k.slice(filter.length));
|
278 | 247 | }
|
279 | 248 | return keys;
|
280 | 249 | }
|
281 |
| - return undefined; |
| 250 | + |
| 251 | + const { result, exceptionDetails } = |
| 252 | + await this.eval(wrapObjectLiteralExpressionIfNeeded(buffer), false, true); |
| 253 | + if (exceptionDetails) { |
| 254 | + return undefined; |
| 255 | + } |
| 256 | + return ` // ${await oneLineInspect(result)}`; |
282 | 257 | }
|
283 | 258 | }
|
284 | 259 |
|
|
0 commit comments