Parse to extract all scopes and bindings.#3852
Conversation
codehag
left a comment
There was a problem hiding this comment.
Phew! great work here. a few comments. let me know if you have questions
| parent: TempScope | null, | ||
| loc: BabelLocation | ||
| ): TempScope { | ||
| let result = { |
| parent, | ||
| scopes: [], | ||
| loc: loc, | ||
| names: Object.create(null) |
There was a problem hiding this comment.
why do we want to use Object.create here?
| function _parseDeclarator( | ||
| declaratorId: Node, | ||
| targetScope: TempScope, | ||
| kind: string |
There was a problem hiding this comment.
type might be a bit clearer here
| let result = { | ||
| type, | ||
| parent, | ||
| scopes: [], |
There was a problem hiding this comment.
this might be renamed children?
| name: string, | ||
| loc: BabelLocation | ||
| ) { | ||
| for (let s = scope; s; s = s.parent) { |
There was a problem hiding this comment.
it is hard to tell what is going on here. if i am guessing i would say we are traversing the temp scope s via the parents, as long as we have a truthy s object. and within this loop we are taking... the first? name from the array names, and pushing the start location. probably to add up the locations until we have a line number value.
I gave it a try myself... not sure it is any better
traverseTempScope(tempScope, callback) {
function _recurse(s) {
if (!s) return;
if (name in s.names) {
callback(s.names[name].refs)
}
return _recurse(s.parent, callback);
}
}
function _recordIdentifierPosition(scope, name, loc) {
_traverseTempScope(
scope,
(nameRefs) => nameRefs.push(loc.start)
)
}There was a problem hiding this comment.
The recursive functions (even with tails call) are not really efficient in comparison with just a loop. I recommend to not introduce any unneeded recursion for simple algorithms, and in this case simple loop easier to read.
| let search = parsedScopes; | ||
| let found = []; | ||
| while (search) { | ||
| let foundOne = search.some(s => { |
There was a problem hiding this comment.
search.some stops execution after one is found; but we are modifying the found array here and the search object. perhaps what we want here again is reduce?
const found = search.reduce((found, s) => {
if (
_compareLocations(s.start, location) <= 0 &&
_compareLocations(location, s.end) < 0
) {
return [s, ...found];
}
return found;
})you can also factor that out into an independant function and do (imagining that the reduce is its own function, and the map is another):
return search.reduce(findLocations).map(createScope);|
|
||
| import type { Source, SourceId } from "debugger-html"; | ||
|
|
||
| var cachedSources = new Map(); |
There was a problem hiding this comment.
why do we want to use var here? would let work?
| return a.line == b.line ? a.column - b.column : a.line - b.line; | ||
| } | ||
|
|
||
| var parsedScopesCache = new Map(); |
There was a problem hiding this comment.
we are using var here, is there a particular reason? i would expect let to be used in this case
| if (!cachedSources.has(sourceId)) { | ||
| throw new Error(`${sourceId} was not provided.`); | ||
| } | ||
| // $FlowIgnore |
There was a problem hiding this comment.
Even if I did the check above, flow is convinced cacheSources.get can be undefined. Changing to ((x: any): Source) cast.
|
|
||
| describe("Parser.getScopes", () => { | ||
| it("parses simple generated/minified es5 source", () => { | ||
| const source = { |
There was a problem hiding this comment.
nit: we can use the parser's test helper and save this in its own file i think
its used via
import { getSource } from "../helpers";
//...
const source = getSource("getScopes/source1");| }); | ||
| } | ||
|
|
||
| function _parseJSScopes(source: Source) { |
There was a problem hiding this comment.
what do the _ signify in these function names?
There was a problem hiding this comment.
thats what i thought, but wouldn't it be private by default, since it isnt exported?
e0f9e89 to
827424c
Compare
827424c to
797f6a4
Compare
|
Moved scope parsing related code to the firefox-devtools/devtools-core#656 |
jasonLaster
left a comment
There was a problem hiding this comment.
Looks like a good start.
I don’t see where getScopes is used yet.
I mentioned this in a comment, but I think we can open a separate issue / PR for switching to a sources cache. I like it, but it is tough to review both changes at once
|
|
||
| export function clearSources() { | ||
| cachedSources = new Map(); | ||
| } |
There was a problem hiding this comment.
almost all of our APIs now expect to get a source.
I agree that this is a performance issue, but I think we should make the fix in a separate PR, that touches all of the spots.
https://github.com/devtools-html/debugger.html/blob/master/src/utils/parser/steps.js#L6-L8
https://github.com/devtools-html/debugger.html/blob/master/src/utils/parser/getSymbols.js#L335-L336
797f6a4 to
b476c20
Compare
Codecov Report
@@ Coverage Diff @@
## master #3852 +/- ##
=========================================
- Coverage 55.05% 55% -0.05%
=========================================
Files 132 132
Lines 5115 5123 +8
Branches 1051 1052 +1
=========================================
+ Hits 2816 2818 +2
- Misses 2299 2305 +6
Continue to review full report at Codecov.
|
|
Depends on #4008 |
d61366c to
ff305fb
Compare
ff305fb to
ba8877d
Compare
Associated Issue: #3817
Summary of Changes