UNPKG

chrome-devtools-frontend

Version:
46 lines (39 loc) 1.83 kB
// Copyright 2023 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Formatter from '../../models/formatter/formatter.js'; import * as TextUtils from '../../models/text_utils/text_utils.js'; import type {Script} from './Script.js'; type ScopeTreeNode = Formatter.FormatterWorkerPool.ScopeTreeNode; type Text = TextUtils.Text.Text; /** If a script failed to parse, we stash null in order to prevent unnecessary re-parsing */ const scopeTrees = new WeakMap<Script, Promise<{scopeTree: ScopeTreeNode, text: Text}|null>>(); /** * Computes and caches the scope tree for `script`. * * We use {@link Script} as a key to uniquely identify scripts. * {@link Script} boils down to "target" + "script ID". This * duplicates work in case of identical script running on multiple targets * (e.g. workers). * * We also return a {@link TextUtils.Text.Text} instance. The scope tree uses offsets * and the text allows conversion from/to line/column numbers. */ export function scopeTreeForScript(script: Script): Promise<{scopeTree: ScopeTreeNode, text: Text}|null> { let promise = scopeTrees.get(script); if (promise === undefined) { promise = script.requestContentData().then(content => { if (TextUtils.ContentData.ContentData.isError(content)) { return null; } const sourceType = script.isModule ? 'module' : 'script'; return Formatter.FormatterWorkerPool.formatterWorkerPool() .javaScriptScopeTree(content.text, sourceType) .then(scopeTree => scopeTree ? ({scopeTree, text: content.textObj}) : null) .catch(() => null); }); scopeTrees.set(script, promise); } // We intentionally return `null` here if the script already failed to parse once. return promise; }