Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ["webpack:///C:/src/github.com/janodvarko/debugger.html/src/utils/pause/mapScopes/locColumn.js",{"id":"server2.conn2.child1/source26/originalSource-d8b8cf0062e8403007261efaebc48a26","url":"webpack:///C:/src/github.com/janodvarko/debugger.html/src/utils/pause/mapScopes/index.js","isBlackBoxed":false,"isPrettyPrinted":false,"isWasm":false,"text":"/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */\n\n// @flow\n\nimport {\n getScopes,\n type SourceScope,\n type BindingData,\n type BindingLocation\n} from \"../../../workers/parser\";\nimport type { RenderableScope } from \"../scopes/getScope\";\nimport { locColumn } from \"./locColumn\";\nimport {\n loadRangeMetadata,\n findMatchingRange,\n type MappedOriginalRange\n} from \"./rangeMetadata\";\n\n// eslint-disable-next-line max-len\nimport {\n findGeneratedBindingForImportBinding,\n findGeneratedBindingForStandardBinding,\n findGeneratedBindingForNormalDeclaration,\n findGeneratedBindingForImportDeclaration,\n type GeneratedDescriptor\n} from \"./findGeneratedBindingFromPosition\";\nimport {\n buildGeneratedBindingList,\n type GeneratedBindingLocation\n} from \"./buildGeneratedBindingList\";\n\nimport { log } from \"../../log\";\nimport type {\n Position,\n Frame,\n Scope,\n Source,\n BindingContents,\n ScopeBindings\n} from \"../../../types\";\n\nexport type OriginalScope = RenderableScope;\n\nexport async function buildMappedScopes(\n source: Source,\n frame: Frame,\n scopes: Scope,\n sourceMaps: any,\n client: any\n): Promise<?{\n mappings: {\n [string]: string\n },\n scope: OriginalScope\n}> {\n const originalAstScopes = await getScopes(frame.location);\n const generatedAstScopes = await getScopes(frame.generatedLocation);\n\n if (!originalAstScopes || !generatedAstScopes) {\n return null;\n }\n\n const generatedAstBindings = buildGeneratedBindingList(\n scopes,\n generatedAstScopes,\n frame.this\n );\n\n const originalRanges = await loadRangeMetadata(\n source,\n frame,\n originalAstScopes,\n sourceMaps\n );\n\n const {\n mappedOriginalScopes,\n expressionLookup\n } = await mapOriginalBindingsToGenerated(\n source,\n originalRanges,\n originalAstScopes,\n generatedAstBindings,\n client,\n sourceMaps\n );\n\n const mappedGeneratedScopes = generateClientScope(\n scopes,\n mappedOriginalScopes\n );\n\n return isReliableScope(mappedGeneratedScopes)\n ? { mappings: expressionLookup, scope: mappedGeneratedScopes }\n : null;\n}\n\nasync function mapOriginalBindingsToGenerated(\n source: Source,\n originalRanges: Array<MappedOriginalRange>,\n originalAstScopes,\n generatedAstBindings,\n client,\n sourceMaps\n) {\n const expressionLookup = {};\n const mappedOriginalScopes = [];\n\n const cachedSourceMaps = batchScopeMappings(\n originalAstScopes,\n source,\n sourceMaps\n );\n\n for (const item of originalAstScopes) {\n const generatedBindings = {};\n\n for (const name of Object.keys(item.bindings)) {\n const binding = item.bindings[name];\n\n const result = await findGeneratedBinding(\n cachedSourceMaps,\n client,\n source,\n name,\n binding,\n originalRanges,\n generatedAstBindings\n );\n\n if (result) {\n generatedBindings[name] = result.grip;\n\n if (\n binding.refs.length !== 0 &&\n // These are assigned depth-first, so we don't want shadowed\n // bindings in parent scopes overwriting the expression.\n !Object.prototype.hasOwnProperty.call(expressionLookup, name)\n ) {\n expressionLookup[name] = result.expression;\n }\n }\n }\n\n mappedOriginalScopes.push({\n ...item,\n generatedBindings\n });\n }\n\n return {\n mappedOriginalScopes,\n expressionLookup\n };\n}\n\n/**\n * Consider a scope and its parents reliable if the vast majority of its\n * bindings were successfully mapped to generated scope bindings.\n */\nfunction isReliableScope(scope: OriginalScope): boolean {\n let totalBindings = 0;\n let unknownBindings = 0;\n\n for (let s = scope; s; s = s.parent) {\n const vars = (s.bindings && s.bindings.variables) || {};\n for (const key of Object.keys(vars)) {\n const binding = vars[key];\n\n totalBindings += 1;\n if (\n binding.value &&\n typeof binding.value === \"object\" &&\n (binding.value.type === \"unscoped\" || binding.value.type === \"unmapped\")\n ) {\n unknownBindings += 1;\n }\n }\n }\n\n // As determined by fair dice roll.\n return totalBindings === 0 || unknownBindings / totalBindings < 0.1;\n}\n\nfunction batchScopeMappings(\n originalAstScopes: Array<SourceScope>,\n source: Source,\n sourceMaps: any\n) {\n const precalculatedRanges = new Map();\n const precalculatedLocations = new Map();\n\n // Explicitly dispatch all of the sourcemap requests synchronously up front so\n // that they will be batched into a single request for the worker to process.\n for (const item of originalAstScopes) {\n for (const name of Object.keys(item.bindings)) {\n for (const ref of item.bindings[name].refs) {\n const locs = [ref];\n if (ref.type !== \"ref\") {\n locs.push(ref.declaration);\n }\n\n for (const loc of locs) {\n precalculatedRanges.set(\n buildLocationKey(loc.start),\n sourceMaps.getGeneratedRanges(loc.start, source)\n );\n precalculatedLocations.set(\n buildLocationKey(loc.start),\n sourceMaps.getGeneratedLocation(loc.start, source)\n );\n precalculatedLocations.set(\n buildLocationKey(loc.end),\n sourceMaps.getGeneratedLocation(loc.end, source)\n );\n }\n }\n }\n }\n\n return {\n async getGeneratedRanges(pos, s) {\n const key = buildLocationKey(pos);\n\n if (s !== source || !precalculatedRanges.has(key)) {\n log(\"Bad precalculated mapping\");\n return sourceMaps.getGeneratedRanges(pos, s);\n }\n return precalculatedRanges.get(key);\n },\n async getGeneratedLocation(pos, s) {\n const key = buildLocationKey(pos);\n\n if (s !== source || !precalculatedLocations.has(key)) {\n log(\"Bad precalculated mapping\");\n return sourceMaps.getGeneratedLocation(pos, s);\n }\n return precalculatedLocations.get(key);\n }\n };\n}\nfunction buildLocationKey(loc: Position): string {\n return `${loc.line}:${locColumn(loc)}`;\n}\n\nfunction generateClientScope(\n scopes: Scope,\n originalScopes: Array<SourceScope & { generatedBindings: ScopeBindings }>\n): OriginalScope {\n // Pull the root object scope and root lexical scope to reuse them in\n // our mapped scopes. This assumes that file file being processed is\n // a CommonJS or ES6 module, which might not be ideal. Potentially\n // should add some logic to try to detect those cases?\n let globalLexicalScope: ?OriginalScope = null;\n for (let s = scopes; s.parent; s = s.parent) {\n // $FlowIgnore - Flow doesn't like casting 'parent'.\n globalLexicalScope = s;\n }\n if (!globalLexicalScope) {\n throw new Error(\"Assertion failure - there should always be a scope\");\n }\n\n // Build a structure similar to the client's linked scope object using\n // the original AST scopes, but pulling in the generated bindings\n // linked to each scope.\n const result = originalScopes\n .slice(0, -2)\n .reverse()\n .reduce((acc, orig, i): OriginalScope => {\n const {\n // The 'this' binding data we have is handled independently, so\n // the binding data is not included here.\n // eslint-disable-next-line no-unused-vars\n this: _this,\n ...variables\n } = orig.generatedBindings;\n\n return {\n parent: acc,\n actor: `originalActor${i}`,\n type: orig.type,\n bindings: {\n arguments: [],\n variables\n },\n ...(orig.type === \"function\"\n ? {\n function: {\n displayName: orig.displayName\n }\n }\n : null),\n ...(orig.type === \"block\"\n ? {\n block: {\n displayName: orig.displayName\n }\n }\n : null)\n };\n }, globalLexicalScope);\n\n // The rendering logic in getScope 'this' bindings only runs on the current\n // selected frame scope, so we pluck out the 'this' binding that was mapped,\n // and put it in a special location\n const thisScope = originalScopes.find(scope => scope.bindings.this);\n if (thisScope) {\n result.bindings.this = thisScope.generatedBindings.this || null;\n }\n\n return result;\n}\n\nfunction hasValidIdent(range: MappedOriginalRange, pos: BindingLocation) {\n return (\n range.type === \"match\" ||\n // For declarations, we allow the range on the identifier to be a\n // more general \"contains\" to increase the chances of a match.\n (pos.type !== \"ref\" && range.type === \"contains\")\n );\n}\n\n// eslint-disable-next-line complexity\nasync function findGeneratedBinding(\n sourceMaps: any,\n client: any,\n source: Source,\n name: string,\n originalBinding: BindingData,\n originalRanges: Array<MappedOriginalRange>,\n generatedAstBindings: Array<GeneratedBindingLocation>\n): Promise<?{\n grip: BindingContents,\n expression: string | null\n}> {\n // If there are no references to the implicits, then we have no way to\n // even attempt to map it back to the original since there is no location\n // data to use. Bail out instead of just showing it as unmapped.\n if (\n originalBinding.type === \"implicit\" &&\n !originalBinding.refs.some(item => item.type === \"ref\")\n ) {\n return null;\n }\n\n const { refs } = originalBinding;\n\n let genContent: GeneratedDescriptor | null = null;\n for (const pos of refs) {\n const range = findMatchingRange(originalRanges, pos);\n if (range && hasValidIdent(range, pos)) {\n if (originalBinding.type === \"import\") {\n genContent = await findGeneratedBindingForImportBinding(\n sourceMaps,\n client,\n source,\n pos,\n name,\n originalBinding.type,\n generatedAstBindings\n );\n } else {\n genContent = await findGeneratedBindingForStandardBinding(\n sourceMaps,\n client,\n source,\n pos,\n name,\n originalBinding.type,\n generatedAstBindings\n );\n }\n }\n\n if (\n (pos.type === \"class-decl\" || pos.type === \"class-inner\") &&\n source.contentType &&\n source.contentType.match(/\\/typescript/)\n ) {\n const declRange = findMatchingRange(originalRanges, pos.declaration);\n if (declRange && declRange.type !== \"multiple\") {\n // Resolve to first binding in the range\n const declContent = await findGeneratedBindingForNormalDeclaration(\n sourceMaps,\n client,\n source,\n pos,\n name,\n originalBinding.type,\n generatedAstBindings\n );\n\n if (declContent) {\n // Prefer the declaration mapping in this case because TS sometimes\n // maps class declaration names to \"export.Foo = Foo;\" or to\n // the decorator logic itself\n genContent = declContent;\n }\n }\n }\n\n if (\n !genContent &&\n (pos.type === \"import-decl\" || pos.type === \"import-ns-decl\")\n ) {\n const declRange = findMatchingRange(originalRanges, pos.declaration);\n\n // The import declaration should have an original position mapping,\n // but otherwise we don't really have preferences on the range type\n // because it can have multiple bindings, but we do want to make sure\n // that all of the bindings that match the range are part of the same\n // import declaration.\n if (declRange && declRange.singleDeclaration) {\n // match the import declaration location\n genContent = await findGeneratedBindingForImportDeclaration(\n sourceMaps,\n client,\n source,\n pos,\n name,\n originalBinding.type,\n generatedAstBindings\n );\n }\n }\n\n if (genContent) {\n break;\n }\n }\n\n if (genContent && genContent.desc) {\n return {\n grip: genContent.desc,\n expression: genContent.expression\n };\n } else if (genContent) {\n // If there is no descriptor for 'this', then this is not the top-level\n // 'this' that the server gave us a binding for, and we can just ignore it.\n if (name === \"this\") {\n return null;\n }\n\n // If the location is found but the descriptor is not, then it\n // means that the server scope information didn't match the scope\n // information from the DevTools parsed scopes.\n return {\n grip: {\n configurable: false,\n enumerable: true,\n writable: false,\n value: {\n type: \"unscoped\",\n unscoped: true,\n\n // HACK: Until support for \"unscoped\" lands in devtools-reps,\n // this will make these show as (unavailable).\n missingArguments: true\n }\n },\n expression: null\n };\n }\n\n // If no location mapping is found, then the map is bad, or\n // the map is okay but it original location is inside\n // of some scope, but the generated location is outside, leading\n // us to search for bindings that don't technically exist.\n return {\n grip: {\n configurable: false,\n enumerable: true,\n writable: false,\n value: {\n type: \"unmapped\",\n unmapped: true,\n\n // HACK: Until support for \"unmapped\" lands in devtools-reps,\n // this will make these show as (unavailable).\n missingArguments: true\n }\n },\n expression: null\n };\n}\n\n\n\n// WEBPACK FOOTER //\n// C:/src/github.com/janodvarko/debugger.html/src/utils/pause/mapScopes/index.js","contentType":"text/javascript","loadedState":"loaded"},"http://localhost:8000/assets/build/debugger.js","webpack:///C:/src/github.com/janodvarko/debugger.html/src/utils/pause/mapScopes/index.js","http://10.0.3.111:8080/www/xhr-spy/tests.js","http://10.0.3.111:8080/www/wasm/import.wasm","http://10.0.3.111:8080/www/wasm/","http://10.0.3.111:8080/www/wasm/test.wasm","http://10.0.3.111:8080/www/wasm/index.js",{"id":"server2.conn4.child1/source78","url":"https://mdn.github.io/webassembly-examples/js-api-examples/fail.wasm","sourceMapURL":null,"isBlackBoxed":false,"isPrettyPrinted":false,"isWasm":true,"text":{"binary":"\u0000asm\u0001\u0000\u0000\u0000\u0001 \u0000\u0001`\u0000\u0001\u0003\u0000\u0001\u0000\u0006\u0000\u0000\u0007\u0000\u0001\u0007fail_me\u0000\u0000\n\u0000\u0001\u0000\u0000A\u0001A\u0000m\u000b"},"contentType":"text/wasm","loadedState":"loaded"},"https://mdn.github.io/webassembly-examples/js-api-examples/fail.html","https://mdn.github.io/webassembly-examples/js-api-examples/fail.wasm","http://localhost:3000/static/js/C:/src/www/my-react-app2/src/App.js","http://10.0.3.111:8080/www/xhr-spy/main.js","http://10.0.3.111:8080/www/xhr-spy/","http://localhost:8080/github.com/janodvarko/harviewer/webapp/scripts/preview/harModel.js","webpack:///~/react-dom/lib/ReactMount.js","webpack:///~/react-dom/lib/ReactCompositeComponent.js","webpack:///src/App.js","http://localhost:3000/static/js/bundle.js","wasm:https://lukewagner.github.io/test-wasm-stacks/%20line%2057%20%3E%20WebAssembly.instantiate","https://lukewagner.github.io/test-wasm-stacks/","http://10.0.3.111:8080/www/xhr-spy/index.js"]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement