chrome-devtools-mcp 0.24.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +23 -6
  2. package/build/src/McpPage.js +4 -4
  3. package/build/src/McpResponse.js +18 -16
  4. package/build/src/TextSnapshot.js +2 -2
  5. package/build/src/ToolHandler.js +188 -0
  6. package/build/src/bin/chrome-devtools-cli-options.js +28 -5
  7. package/build/src/bin/chrome-devtools-mcp-cli-options.js +8 -5
  8. package/build/src/bin/chrome-devtools-mcp-main.js +4 -8
  9. package/build/src/bin/chrome-devtools.js +0 -2
  10. package/build/src/index.js +9 -164
  11. package/build/src/telemetry/ClearcutLogger.js +27 -0
  12. package/build/src/telemetry/errors.js +14 -0
  13. package/build/src/telemetry/types.js +0 -8
  14. package/build/src/third_party/THIRD_PARTY_NOTICES +12 -14
  15. package/build/src/third_party/bundled-packages.json +3 -3
  16. package/build/src/third_party/devtools-formatter-worker.js +49 -33
  17. package/build/src/third_party/devtools-heap-snapshot-worker.js +60 -44
  18. package/build/src/third_party/index.js +2138 -1352
  19. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolDescription.md +5 -0
  20. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +5 -0
  21. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +5 -0
  22. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
  23. package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
  24. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +4236 -4219
  25. package/build/src/tools/categories.js +6 -3
  26. package/build/src/tools/input.js +72 -7
  27. package/build/src/tools/lighthouse.js +7 -7
  28. package/build/src/tools/pages.js +5 -5
  29. package/build/src/tools/{inPage.js → thirdPartyDeveloper.js} +15 -15
  30. package/build/src/tools/tools.js +2 -2
  31. package/build/src/tools/webmcp.js +2 -4
  32. package/build/src/version.js +1 -1
  33. package/package.json +7 -8
@@ -7,77 +7,16 @@ import { ensureBrowserConnected, ensureBrowserLaunched } from './browser.js';
7
7
  import { loadIssueDescriptions } from './issue-descriptions.js';
8
8
  import { logger } from './logger.js';
9
9
  import { McpContext } from './McpContext.js';
10
- import { McpResponse } from './McpResponse.js';
11
10
  import { Mutex } from './Mutex.js';
12
- import { SlimMcpResponse } from './SlimMcpResponse.js';
13
11
  import { ClearcutLogger } from './telemetry/ClearcutLogger.js';
14
- import { bucketizeLatency } from './telemetry/metricUtils.js';
15
12
  import { McpServer, SetLevelRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, } from './third_party/index.js';
16
- import { labels, OFF_BY_DEFAULT_CATEGORIES } from './tools/categories.js';
17
- import { pageIdSchema } from './tools/ToolDefinition.js';
13
+ import { ToolHandler } from './ToolHandler.js';
18
14
  import { createTools } from './tools/tools.js';
19
15
  import { VERSION } from './version.js';
20
- export function buildFlag(category) {
21
- return `category${category.charAt(0).toUpperCase() + category.slice(1)}`;
22
- }
23
- function buildDisabledMessage(toolName, flag, categoryLabel) {
24
- const reason = categoryLabel
25
- ? `is in category ${categoryLabel} which`
26
- : `requires experimental feature ${flag} and`;
27
- return `Tool ${toolName} ${reason} is currently disabled. Enable it by running chrome-devtools start ${flag}=true. For more information check the README.`;
28
- }
29
- function getCategoryStatus(category, serverArgs) {
30
- const categoryFlag = buildFlag(category);
31
- const flagValue = serverArgs[categoryFlag];
32
- const isDisabled = OFF_BY_DEFAULT_CATEGORIES.includes(category)
33
- ? !flagValue
34
- : flagValue === false;
35
- if (isDisabled) {
36
- return {
37
- categoryFlag,
38
- disabled: true,
39
- };
40
- }
41
- return {
42
- disabled: false,
43
- };
44
- }
45
- function getConditionStatus(condition, serverArgs) {
46
- if (condition && !serverArgs[condition]) {
47
- return { conditionFlag: condition, disabled: true };
48
- }
49
- return { disabled: false };
50
- }
51
- function getToolStatusInfo(tool, serverArgs) {
52
- const category = tool.annotations.category;
53
- const categoryCheck = getCategoryStatus(category, serverArgs);
54
- if (category && categoryCheck.disabled) {
55
- if (!categoryCheck.categoryFlag) {
56
- throw new Error('when the category is disabled there should always be a flag set');
57
- }
58
- return {
59
- disabled: true,
60
- reason: buildDisabledMessage(tool.name, `--${categoryCheck.categoryFlag}`, labels[category]),
61
- };
62
- }
63
- for (const condition of tool.annotations.conditions || []) {
64
- const conditionCheck = getConditionStatus(condition, serverArgs);
65
- if (conditionCheck.disabled) {
66
- if (!conditionCheck.conditionFlag) {
67
- throw new Error('when the condition is disabled there should always be a flag set');
68
- }
69
- return {
70
- disabled: true,
71
- reason: buildDisabledMessage(tool.name, `--${conditionCheck.conditionFlag}`),
72
- };
73
- }
74
- }
75
- return { disabled: false };
76
- }
16
+ export { buildFlag } from './ToolHandler.js';
77
17
  export async function createMcpServer(serverArgs, options) {
78
- let clearcutLogger;
79
18
  if (serverArgs.usageStatistics) {
80
- clearcutLogger = new ClearcutLogger({
19
+ ClearcutLogger.initialize({
81
20
  logFile: serverArgs.logFile,
82
21
  appVersion: VERSION,
83
22
  clearcutEndpoint: serverArgs.clearcutEndpoint,
@@ -108,7 +47,7 @@ export async function createMcpServer(serverArgs, options) {
108
47
  server.server.oninitialized = () => {
109
48
  const clientName = server.server.getClientVersion()?.name;
110
49
  if (clientName) {
111
- clearcutLogger?.setClientName(clientName);
50
+ ClearcutLogger.get()?.setClientName(clientName);
112
51
  }
113
52
  if (server.server.getClientCapabilities()?.roots) {
114
53
  void updateRoots();
@@ -164,110 +103,16 @@ export async function createMcpServer(serverArgs, options) {
164
103
  }
165
104
  const toolMutex = new Mutex();
166
105
  function registerTool(tool) {
167
- const { disabled, reason: disabledReason } = getToolStatusInfo(tool, serverArgs);
168
- if (disabled && !serverArgs.viaCli) {
106
+ const toolHandler = new ToolHandler(tool, serverArgs, getContext, toolMutex);
107
+ if (!toolHandler.shouldRegister) {
169
108
  return;
170
109
  }
171
- const schema = 'pageScoped' in tool &&
172
- tool.pageScoped &&
173
- serverArgs.experimentalPageIdRouting &&
174
- !serverArgs.slim
175
- ? { ...tool.schema, ...pageIdSchema }
176
- : tool.schema;
177
110
  server.registerTool(tool.name, {
178
111
  description: tool.description,
179
- inputSchema: schema,
112
+ inputSchema: toolHandler.inputSchema,
180
113
  annotations: tool.annotations,
181
114
  }, async (params) => {
182
- if (disabledReason) {
183
- return {
184
- content: [
185
- {
186
- type: 'text',
187
- text: disabledReason,
188
- },
189
- ],
190
- isError: true,
191
- };
192
- }
193
- const guard = await toolMutex.acquire();
194
- const startTime = Date.now();
195
- let success = false;
196
- try {
197
- logger(`${tool.name} request: ${JSON.stringify(params, null, ' ')}`);
198
- const context = await getContext();
199
- logger(`${tool.name} context: resolved`);
200
- await context.detectOpenDevToolsWindows();
201
- const response = serverArgs.slim
202
- ? new SlimMcpResponse(serverArgs)
203
- : new McpResponse(serverArgs);
204
- response.setRedactNetworkHeaders(serverArgs.redactNetworkHeaders);
205
- try {
206
- const page = serverArgs.experimentalPageIdRouting &&
207
- params.pageId &&
208
- !serverArgs.slim
209
- ? context.getPageById(params.pageId)
210
- : context.getSelectedMcpPage();
211
- response.setPage(page);
212
- if (tool.blockedByDialog) {
213
- page.throwIfDialogOpen();
214
- }
215
- if ('pageScoped' in tool && tool.pageScoped) {
216
- await tool.handler({
217
- params,
218
- page,
219
- }, response, context);
220
- }
221
- else {
222
- await tool.handler(
223
- // @ts-expect-error types do not match.
224
- {
225
- params,
226
- }, response, context);
227
- }
228
- }
229
- catch (err) {
230
- response.setError(err);
231
- }
232
- const { content, structuredContent } = await response.handle(tool.name, context);
233
- const result = {
234
- content,
235
- };
236
- if (response.error) {
237
- result.isError = true;
238
- }
239
- success = true;
240
- if (serverArgs.experimentalStructuredContent) {
241
- result.structuredContent = structuredContent;
242
- }
243
- return result;
244
- }
245
- catch (err) {
246
- logger(`${tool.name} error:`, err, err?.stack);
247
- let errorText = err && 'message' in err ? err.message : String(err);
248
- if ('cause' in err && err.cause) {
249
- errorText += `\nCause: ${err.cause.message}`;
250
- }
251
- return {
252
- content: [
253
- {
254
- type: 'text',
255
- text: errorText,
256
- },
257
- ],
258
- isError: true,
259
- };
260
- }
261
- finally {
262
- void clearcutLogger?.logToolInvocation({
263
- toolName: tool.name,
264
- params,
265
- schema,
266
- success,
267
- latencyMs: bucketizeLatency(Date.now() - startTime),
268
- });
269
- guard.dispose();
270
- }
115
+ return await toolHandler.handle(params);
271
116
  });
272
117
  }
273
118
  const tools = createTools(serverArgs);
@@ -275,7 +120,7 @@ export async function createMcpServer(serverArgs, options) {
275
120
  registerTool(tool);
276
121
  }
277
122
  await loadIssueDescriptions();
278
- return { server, clearcutLogger };
123
+ return { server };
279
124
  }
280
125
  export const logDisclaimers = (args) => {
281
126
  console.error(`chrome-devtools-mcp exposes content of the browser instance to the MCP clients allowing them to inspect,
@@ -136,10 +136,25 @@ function detectOsType() {
136
136
  return OsType.OS_TYPE_UNSPECIFIED;
137
137
  }
138
138
  }
139
+ // Not const to allow resetting the instance for testing purposes.
140
+ let _clearcut_logger_instance;
139
141
  export class ClearcutLogger {
140
142
  #persistence;
141
143
  #watchdog;
142
144
  #mcpClient;
145
+ static initialize(options) {
146
+ if (_clearcut_logger_instance) {
147
+ throw new Error('ClearcutLogger is already initialized');
148
+ }
149
+ _clearcut_logger_instance = new ClearcutLogger(options);
150
+ return _clearcut_logger_instance;
151
+ }
152
+ static get() {
153
+ return _clearcut_logger_instance;
154
+ }
155
+ static resetForTesting() {
156
+ _clearcut_logger_instance = undefined;
157
+ }
143
158
  constructor(options) {
144
159
  this.#persistence = options.persistence ?? new FilePersistence();
145
160
  this.#watchdog =
@@ -237,6 +252,18 @@ export class ClearcutLogger {
237
252
  logger('Error in logDailyActiveIfNeeded:', err);
238
253
  }
239
254
  }
255
+ async logServerError(args) {
256
+ this.#watchdog.send({
257
+ type: WatchdogMessageType.LOG_EVENT,
258
+ payload: {
259
+ mcp_client: this.#mcpClient,
260
+ server_error: {
261
+ tool_name: args.toolName ?? '',
262
+ error_code: args.errorCode,
263
+ },
264
+ },
265
+ });
266
+ }
240
267
  #shouldLogDailyActive(state) {
241
268
  if (!state.lastActive) {
242
269
  return true;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * IMPORTANT:
7
+ * 1. this module must only contain ErrorCode.
8
+ * 2. do not refactor ErrorCode to elsewhere.
9
+ */
10
+ export var ErrorCode;
11
+ (function (ErrorCode) {
12
+ ErrorCode[ErrorCode["ERROR_CODE_UNSPECIFIED"] = 0] = "ERROR_CODE_UNSPECIFIED";
13
+ })(ErrorCode || (ErrorCode = {}));
14
+ //# sourceMappingURL=errors.js.map
@@ -11,14 +11,6 @@ export var OsType;
11
11
  OsType[OsType["OS_TYPE_MACOS"] = 2] = "OS_TYPE_MACOS";
12
12
  OsType[OsType["OS_TYPE_LINUX"] = 3] = "OS_TYPE_LINUX";
13
13
  })(OsType || (OsType = {}));
14
- export var ChromeChannel;
15
- (function (ChromeChannel) {
16
- ChromeChannel[ChromeChannel["CHROME_CHANNEL_UNSPECIFIED"] = 0] = "CHROME_CHANNEL_UNSPECIFIED";
17
- ChromeChannel[ChromeChannel["CHROME_CHANNEL_CANARY"] = 1] = "CHROME_CHANNEL_CANARY";
18
- ChromeChannel[ChromeChannel["CHROME_CHANNEL_DEV"] = 2] = "CHROME_CHANNEL_DEV";
19
- ChromeChannel[ChromeChannel["CHROME_CHANNEL_BETA"] = 3] = "CHROME_CHANNEL_BETA";
20
- ChromeChannel[ChromeChannel["CHROME_CHANNEL_STABLE"] = 4] = "CHROME_CHANNEL_STABLE";
21
- })(ChromeChannel || (ChromeChannel = {}));
22
14
  export var McpClient;
23
15
  (function (McpClient) {
24
16
  McpClient[McpClient["MCP_CLIENT_UNSPECIFIED"] = 0] = "MCP_CLIENT_UNSPECIFIED";
@@ -324,7 +324,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE
324
324
 
325
325
  Name: semver
326
326
  URL: git+https://github.com/npm/node-semver.git
327
- Version: 7.7.4
327
+ Version: 7.8.0
328
328
  License: ISC
329
329
 
330
330
  The ISC License
@@ -617,15 +617,13 @@ SOFTWARE.
617
617
 
618
618
  Name: fast-uri
619
619
  URL: https://github.com/fastify/fast-uri
620
- Version: 3.1.0
620
+ Version: 3.1.2
621
621
  License: BSD-3-Clause
622
622
 
623
623
  Copyright (c) 2011-2021, Gary Court until https://github.com/garycourt/uri-js/commit/a1acf730b4bba3f1097c9f52e7d9d3aba8cdcaae
624
- Copyright (c) 2021-present The Fastify team
624
+ Copyright (c) 2021-present The Fastify team <https://github.com/fastify/fastify#team>
625
625
  All rights reserved.
626
626
 
627
- The Fastify team members are listed at https://github.com/fastify/fastify#team.
628
-
629
627
  Redistribution and use in source and binary forms, with or without
630
628
  modification, are permitted provided that the following conditions are met:
631
629
  * Redistributions of source code must retain the above copyright
@@ -869,14 +867,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
869
867
 
870
868
  Name: puppeteer-core
871
869
  URL: https://github.com/puppeteer/puppeteer/tree/main/packages/puppeteer-core
872
- Version: 24.42.0
870
+ Version: 24.43.0
873
871
  License: Apache-2.0
874
872
 
875
873
  -------------------- DEPENDENCY DIVIDER --------------------
876
874
 
877
875
  Name: @puppeteer/browsers
878
876
  URL: https://github.com/puppeteer/puppeteer/tree/main/packages/browsers
879
- Version: 2.13.0
877
+ Version: 2.13.1
880
878
  License: Apache-2.0
881
879
 
882
880
  -------------------- DEPENDENCY DIVIDER --------------------
@@ -1145,7 +1143,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1145
1143
 
1146
1144
  Name: ip-address
1147
1145
  URL: git://github.com/beaugunderson/ip-address.git
1148
- Version: 10.1.0
1146
+ Version: 10.2.0
1149
1147
  License: MIT
1150
1148
 
1151
1149
  Copyright (C) 2011 by Beau Gunderson
@@ -1264,7 +1262,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1264
1262
 
1265
1263
  Name: basic-ftp
1266
1264
  URL: https://github.com/patrickjuchli/basic-ftp.git
1267
- Version: 5.3.0
1265
+ Version: 5.3.1
1268
1266
  License: MIT
1269
1267
 
1270
1268
  Copyright (c) 2019 Patrick Juchli
@@ -1598,7 +1596,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1598
1596
 
1599
1597
  Name: ws
1600
1598
  URL: https://github.com/websockets/ws
1601
- Version: 8.19.0
1599
+ Version: 8.20.0
1602
1600
  License: MIT
1603
1601
 
1604
1602
  Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
@@ -3988,7 +3986,7 @@ SOFTWARE.
3988
3986
 
3989
3987
  Name: puppeteer-core
3990
3988
  URL: https://github.com/puppeteer/puppeteer/tree/main/packages/puppeteer-core
3991
- Version: 24.42.0
3989
+ Version: 24.43.0
3992
3990
  License: Apache-2.0
3993
3991
 
3994
3992
  -------------------- DEPENDENCY DIVIDER --------------------
@@ -4054,7 +4052,7 @@ SOFTWARE.
4054
4052
 
4055
4053
  Name: tldts-core
4056
4054
  URL: https://github.com/remusao/tldts#readme
4057
- Version: 7.0.29
4055
+ Version: 7.0.30
4058
4056
  License: MIT
4059
4057
 
4060
4058
  Copyright (c) 2017 Thomas Parisot, 2018 Rémi Berson
@@ -4076,7 +4074,7 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTH
4076
4074
 
4077
4075
  Name: tldts-icann
4078
4076
  URL: https://github.com/remusao/tldts#readme
4079
- Version: 7.0.29
4077
+ Version: 7.0.30
4080
4078
  License: MIT
4081
4079
 
4082
4080
  Copyright (c) 2017 Thomas Parisot, 2018 Rémi Berson
@@ -4118,7 +4116,7 @@ PERFORMANCE OF THIS SOFTWARE.
4118
4116
 
4119
4117
  Name: web-features
4120
4118
  URL: git+https://github.com/web-platform-dx/web-features.git
4121
- Version: 3.25.0
4119
+ Version: 3.26.0
4122
4120
  License: Apache-2.0
4123
4121
 
4124
4122
  Apache License
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "@modelcontextprotocol/sdk": "1.29.0",
3
- "chrome-devtools-frontend": "1.0.1618066",
3
+ "chrome-devtools-frontend": "1.0.1626840",
4
4
  "core-js": "3.49.0",
5
5
  "debug": "4.4.3",
6
- "lighthouse": "13.2.0",
6
+ "lighthouse": "13.3.0",
7
7
  "semver": "^7.7.4",
8
8
  "urlpattern-polyfill": "^10.1.0",
9
9
  "yargs": "18.0.0",
10
- "puppeteer-core": "24.42.0"
10
+ "puppeteer-core": "24.43.0"
11
11
  }
@@ -85,6 +85,15 @@ const HOST_RUNTIME$2 = {
85
85
  return new WebWorker(url);
86
86
  },
87
87
  workerScope: new WebWorkerScope(),
88
+ getOnLine() {
89
+ return navigator.onLine;
90
+ },
91
+ getUserAgent() {
92
+ return navigator.userAgent;
93
+ },
94
+ getLocalStorage() {
95
+ return 'localStorage' in globalThis ? globalThis.localStorage : undefined;
96
+ },
88
97
  };
89
98
 
90
99
  var HostRuntime$1 = /*#__PURE__*/Object.freeze({
@@ -167,6 +176,15 @@ const HOST_RUNTIME$1 = {
167
176
  return new NodeWorker(url);
168
177
  },
169
178
  workerScope: new NodeWorkerScope(),
179
+ getOnLine() {
180
+ return true;
181
+ },
182
+ getUserAgent() {
183
+ return 'Node.js';
184
+ },
185
+ getLocalStorage() {
186
+ return undefined;
187
+ },
170
188
  };
171
189
 
172
190
  var HostRuntime = /*#__PURE__*/Object.freeze({
@@ -2626,10 +2644,8 @@ var ExperimentName;
2626
2644
  (function (ExperimentName) {
2627
2645
  ExperimentName["ALL"] = "*";
2628
2646
  ExperimentName["CAPTURE_NODE_CREATION_STACKS"] = "capture-node-creation-stacks";
2629
- ExperimentName["LIVE_HEAP_PROFILE"] = "live-heap-profile";
2630
2647
  ExperimentName["PROTOCOL_MONITOR"] = "protocol-monitor";
2631
2648
  ExperimentName["TIMELINE_INVALIDATION_TRACKING"] = "timeline-invalidation-tracking";
2632
- ExperimentName["FONT_EDITOR"] = "font-editor";
2633
2649
  ExperimentName["INSTRUMENTATION_BREAKPOINTS"] = "instrumentation-breakpoints";
2634
2650
  ExperimentName["USE_SOURCE_MAP_SCOPES"] = "use-source-map-scopes";
2635
2651
  ExperimentName["TIMELINE_DEBUG_MODE"] = "timeline-debug-mode";
@@ -3329,12 +3345,12 @@ pp$9.isSimpleAssignTarget = function (expr) {
3329
3345
  };
3330
3346
  var pp$8 = Parser$1.prototype;
3331
3347
  pp$8.parseTopLevel = function (node) {
3332
- var exports$1 = Object.create(null);
3348
+ var exports = Object.create(null);
3333
3349
  if (!node.body) {
3334
3350
  node.body = [];
3335
3351
  }
3336
3352
  while (this.type !== types$1.eof) {
3337
- var stmt = this.parseStatement(null, true, exports$1);
3353
+ var stmt = this.parseStatement(null, true, exports);
3338
3354
  node.body.push(stmt);
3339
3355
  }
3340
3356
  if (this.inModule) {
@@ -3392,7 +3408,7 @@ pp$8.isAsyncFunction = function () {
3392
3408
  (next + 8 === this.input.length ||
3393
3409
  !(isIdentifierChar(after = this.input.charCodeAt(next + 8)) || after > 0xd7ff && after < 0xdc00));
3394
3410
  };
3395
- pp$8.parseStatement = function (context, topLevel, exports$1) {
3411
+ pp$8.parseStatement = function (context, topLevel, exports) {
3396
3412
  var starttype = this.type, node = this.startNode(), kind;
3397
3413
  if (this.isLet(context)) {
3398
3414
  starttype = types$1._var;
@@ -3449,7 +3465,7 @@ pp$8.parseStatement = function (context, topLevel, exports$1) {
3449
3465
  this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'");
3450
3466
  }
3451
3467
  }
3452
- return starttype === types$1._import ? this.parseImport(node) : this.parseExport(node, exports$1);
3468
+ return starttype === types$1._import ? this.parseImport(node) : this.parseExport(node, exports);
3453
3469
  default:
3454
3470
  if (this.isAsyncFunction()) {
3455
3471
  if (context) {
@@ -4126,11 +4142,11 @@ function checkKeyName(node, name) {
4126
4142
  return !computed && (key.type === "Identifier" && key.name === name ||
4127
4143
  key.type === "Literal" && key.value === name);
4128
4144
  }
4129
- pp$8.parseExportAllDeclaration = function (node, exports$1) {
4145
+ pp$8.parseExportAllDeclaration = function (node, exports) {
4130
4146
  if (this.options.ecmaVersion >= 11) {
4131
4147
  if (this.eatContextual("as")) {
4132
4148
  node.exported = this.parseModuleExportName();
4133
- this.checkExport(exports$1, node.exported, this.lastTokStart);
4149
+ this.checkExport(exports, node.exported, this.lastTokStart);
4134
4150
  }
4135
4151
  else {
4136
4152
  node.exported = null;
@@ -4144,30 +4160,30 @@ pp$8.parseExportAllDeclaration = function (node, exports$1) {
4144
4160
  this.semicolon();
4145
4161
  return this.finishNode(node, "ExportAllDeclaration");
4146
4162
  };
4147
- pp$8.parseExport = function (node, exports$1) {
4163
+ pp$8.parseExport = function (node, exports) {
4148
4164
  this.next();
4149
4165
  if (this.eat(types$1.star)) {
4150
- return this.parseExportAllDeclaration(node, exports$1);
4166
+ return this.parseExportAllDeclaration(node, exports);
4151
4167
  }
4152
4168
  if (this.eat(types$1._default)) {
4153
- this.checkExport(exports$1, "default", this.lastTokStart);
4169
+ this.checkExport(exports, "default", this.lastTokStart);
4154
4170
  node.declaration = this.parseExportDefaultDeclaration();
4155
4171
  return this.finishNode(node, "ExportDefaultDeclaration");
4156
4172
  }
4157
4173
  if (this.shouldParseExportStatement()) {
4158
4174
  node.declaration = this.parseExportDeclaration(node);
4159
4175
  if (node.declaration.type === "VariableDeclaration") {
4160
- this.checkVariableExport(exports$1, node.declaration.declarations);
4176
+ this.checkVariableExport(exports, node.declaration.declarations);
4161
4177
  }
4162
4178
  else {
4163
- this.checkExport(exports$1, node.declaration.id, node.declaration.id.start);
4179
+ this.checkExport(exports, node.declaration.id, node.declaration.id.start);
4164
4180
  }
4165
4181
  node.specifiers = [];
4166
4182
  node.source = null;
4167
4183
  }
4168
4184
  else {
4169
4185
  node.declaration = null;
4170
- node.specifiers = this.parseExportSpecifiers(exports$1);
4186
+ node.specifiers = this.parseExportSpecifiers(exports);
4171
4187
  if (this.eatContextual("from")) {
4172
4188
  if (this.type !== types$1.string) {
4173
4189
  this.unexpected();
@@ -4212,57 +4228,57 @@ pp$8.parseExportDefaultDeclaration = function () {
4212
4228
  return declaration;
4213
4229
  }
4214
4230
  };
4215
- pp$8.checkExport = function (exports$1, name, pos) {
4216
- if (!exports$1) {
4231
+ pp$8.checkExport = function (exports, name, pos) {
4232
+ if (!exports) {
4217
4233
  return;
4218
4234
  }
4219
4235
  if (typeof name !== "string") {
4220
4236
  name = name.type === "Identifier" ? name.name : name.value;
4221
4237
  }
4222
- if (hasOwn(exports$1, name)) {
4238
+ if (hasOwn(exports, name)) {
4223
4239
  this.raiseRecoverable(pos, "Duplicate export '" + name + "'");
4224
4240
  }
4225
- exports$1[name] = true;
4241
+ exports[name] = true;
4226
4242
  };
4227
- pp$8.checkPatternExport = function (exports$1, pat) {
4243
+ pp$8.checkPatternExport = function (exports, pat) {
4228
4244
  var type = pat.type;
4229
4245
  if (type === "Identifier") {
4230
- this.checkExport(exports$1, pat, pat.start);
4246
+ this.checkExport(exports, pat, pat.start);
4231
4247
  }
4232
4248
  else if (type === "ObjectPattern") {
4233
4249
  for (var i = 0, list = pat.properties; i < list.length; i += 1) {
4234
4250
  var prop = list[i];
4235
- this.checkPatternExport(exports$1, prop);
4251
+ this.checkPatternExport(exports, prop);
4236
4252
  }
4237
4253
  }
4238
4254
  else if (type === "ArrayPattern") {
4239
4255
  for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
4240
4256
  var elt = list$1[i$1];
4241
4257
  if (elt) {
4242
- this.checkPatternExport(exports$1, elt);
4258
+ this.checkPatternExport(exports, elt);
4243
4259
  }
4244
4260
  }
4245
4261
  }
4246
4262
  else if (type === "Property") {
4247
- this.checkPatternExport(exports$1, pat.value);
4263
+ this.checkPatternExport(exports, pat.value);
4248
4264
  }
4249
4265
  else if (type === "AssignmentPattern") {
4250
- this.checkPatternExport(exports$1, pat.left);
4266
+ this.checkPatternExport(exports, pat.left);
4251
4267
  }
4252
4268
  else if (type === "RestElement") {
4253
- this.checkPatternExport(exports$1, pat.argument);
4269
+ this.checkPatternExport(exports, pat.argument);
4254
4270
  }
4255
4271
  else if (type === "ParenthesizedExpression") {
4256
- this.checkPatternExport(exports$1, pat.expression);
4272
+ this.checkPatternExport(exports, pat.expression);
4257
4273
  }
4258
4274
  };
4259
- pp$8.checkVariableExport = function (exports$1, decls) {
4260
- if (!exports$1) {
4275
+ pp$8.checkVariableExport = function (exports, decls) {
4276
+ if (!exports) {
4261
4277
  return;
4262
4278
  }
4263
4279
  for (var i = 0, list = decls; i < list.length; i += 1) {
4264
4280
  var decl = list[i];
4265
- this.checkPatternExport(exports$1, decl.id);
4281
+ this.checkPatternExport(exports, decl.id);
4266
4282
  }
4267
4283
  };
4268
4284
  pp$8.shouldParseExportStatement = function () {
@@ -4273,14 +4289,14 @@ pp$8.shouldParseExportStatement = function () {
4273
4289
  this.isLet() ||
4274
4290
  this.isAsyncFunction();
4275
4291
  };
4276
- pp$8.parseExportSpecifier = function (exports$1) {
4292
+ pp$8.parseExportSpecifier = function (exports) {
4277
4293
  var node = this.startNode();
4278
4294
  node.local = this.parseModuleExportName();
4279
4295
  node.exported = this.eatContextual("as") ? this.parseModuleExportName() : node.local;
4280
- this.checkExport(exports$1, node.exported, node.exported.start);
4296
+ this.checkExport(exports, node.exported, node.exported.start);
4281
4297
  return this.finishNode(node, "ExportSpecifier");
4282
4298
  };
4283
- pp$8.parseExportSpecifiers = function (exports$1) {
4299
+ pp$8.parseExportSpecifiers = function (exports) {
4284
4300
  var nodes = [], first = true;
4285
4301
  this.expect(types$1.braceL);
4286
4302
  while (!this.eat(types$1.braceR)) {
@@ -4293,7 +4309,7 @@ pp$8.parseExportSpecifiers = function (exports$1) {
4293
4309
  else {
4294
4310
  first = false;
4295
4311
  }
4296
- nodes.push(this.parseExportSpecifier(exports$1));
4312
+ nodes.push(this.parseExportSpecifier(exports));
4297
4313
  }
4298
4314
  return nodes;
4299
4315
  };