|
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,101 @@ 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 inlineEval = async (source) => { |
| 170 | + const { result, exceptionDetails } = |
| 171 | + await this.eval(wrapObjectLiteralExpressionIfNeeded(source), false, true); |
| 172 | + if (exceptionDetails) { |
| 173 | + return undefined; |
| 174 | + } |
| 175 | + return ` // ${await oneLineInspect(result)}`; |
| 176 | + }; |
| 177 | + |
| 178 | + const statement = parseDammit(buffer).body[0]; |
| 179 | + if (statement.type !== 'ExpressionStatement') { |
| 180 | + return undefined; |
| 181 | + } |
| 182 | + const { expression } = statement; |
| 183 | + |
173 | 184 | let keys; |
174 | 185 | let filter; |
175 | | - if (buffer.length === 0) { |
| 186 | + if (expression.type === 'Identifier') { |
176 | 187 | keys = await collectGlobalNames(); |
177 | | - } else { |
178 | | - let expr; |
179 | | - let computed = false; |
180 | | - let leadingQuote = false; |
| 188 | + filter = expression.name; |
181 | 189 |
|
182 | | - let index = buffer.lastIndexOf('.'); |
183 | | - if (index !== -1) { |
184 | | - expr = buffer.slice(0, index); |
185 | | - filter = buffer.slice(index + 1, buffer.length).trim(); |
| 190 | + if (keys.includes(filter)) { |
| 191 | + return inlineEval(buffer); |
186 | 192 | } |
| 193 | + } |
187 | 194 |
|
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 | | - } |
| 195 | + if (expression.type === 'MemberExpression') { |
| 196 | + const expr = buffer.slice(expression.object.start, expression.object.end); |
| 197 | + let leadingQuote = false; |
| 198 | + if (expression.computed && expression.property.type === 'Literal') { |
| 199 | + filter = expression.property.value; |
| 200 | + leadingQuote = expression.property.raw.startsWith('\''); |
| 201 | + } else if (!expression.computed && expression.property.type === 'Identifier') { |
| 202 | + filter = expression.property.name === '✖' ? undefined : expression.property.name; |
196 | 203 | } |
197 | 204 |
|
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 | + const evaluateResult = await this.eval(expr, false, true); |
| 206 | + if (evaluateResult.exceptionDetails) { |
| 207 | + return undefined; |
205 | 208 | } |
206 | 209 |
|
207 | | - if (isCallExpression(filter)) { |
208 | | - expr = undefined; |
209 | | - filter = undefined; |
| 210 | + const own = []; |
| 211 | + const inherited = []; |
| 212 | + (await Runtime.getProperties({ |
| 213 | + objectId: evaluateResult.result.objectId, |
| 214 | + generatePreview: true, |
| 215 | + })) |
| 216 | + .result |
| 217 | + .filter(({ symbol }) => !symbol) |
| 218 | + .forEach(({ isOwn, name }) => { |
| 219 | + if (isOwn) { |
| 220 | + own.push(name); |
| 221 | + } else { |
| 222 | + inherited.push(name); |
| 223 | + } |
| 224 | + }); |
| 225 | + |
| 226 | + keys = [...own, ...inherited]; |
| 227 | + |
| 228 | + if (keys.includes(filter)) { |
| 229 | + return inlineEval(buffer); |
210 | 230 | } |
211 | 231 |
|
212 | | - if (expr) { |
213 | | - const evaluateResult = await this.eval(expr, false, true); |
214 | | - if (evaluateResult.exceptionDetails) { |
215 | | - return undefined; |
216 | | - } |
217 | | - |
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 | | - } |
| 232 | + if (expression.computed) { |
| 233 | + keys = keys.map((key) => { |
| 234 | + let r; |
| 235 | + if (!leadingQuote && `${+key}` === key) { |
| 236 | + r = key; |
| 237 | + } else { |
| 238 | + r = strEscape(key); |
244 | 239 | if (leadingQuote) { |
245 | | - return r.slice(1); |
| 240 | + r = r.slice(1); |
246 | 241 | } |
247 | | - return r; |
248 | | - }); |
249 | | - } else { |
250 | | - keys = k.filter(isIdentifier); |
251 | | - } |
| 242 | + } |
| 243 | + return `${r}]`; |
| 244 | + }); |
252 | 245 | } 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)}`; |
| 246 | + keys = keys.filter(isIdentifier); |
260 | 247 | } |
261 | 248 | } |
262 | 249 |
|
263 | 250 | if (keys) { |
264 | 251 | 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 | 252 | return keys |
276 | 253 | .filter((k) => k.startsWith(filter)) |
277 | 254 | .map((k) => k.slice(filter.length)); |
278 | 255 | } |
279 | 256 | return keys; |
280 | 257 | } |
281 | | - return undefined; |
| 258 | + |
| 259 | + return inlineEval(buffer); |
282 | 260 | } |
283 | 261 | } |
284 | 262 |
|
|
0 commit comments