@theia/core 1.38.0-next.7 → 1.38.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 (116) hide show
  1. package/README.md +6 -6
  2. package/i18n/nls.cs.json +1 -4
  3. package/i18n/nls.de.json +1 -4
  4. package/i18n/nls.es.json +1 -4
  5. package/i18n/nls.fr.json +1 -4
  6. package/i18n/nls.hu.json +1 -4
  7. package/i18n/nls.it.json +1 -4
  8. package/i18n/nls.ja.json +1 -4
  9. package/i18n/nls.json +1 -4
  10. package/i18n/nls.pl.json +1 -4
  11. package/i18n/nls.pt-br.json +1 -4
  12. package/i18n/nls.pt-pt.json +1 -4
  13. package/i18n/nls.ru.json +1 -4
  14. package/i18n/nls.zh-cn.json +1 -4
  15. package/lib/browser/common-frontend-contribution.js +3 -3
  16. package/lib/browser/common-frontend-contribution.js.map +1 -1
  17. package/lib/browser/common-styling-participants.d.ts.map +1 -1
  18. package/lib/browser/common-styling-participants.js +20 -0
  19. package/lib/browser/common-styling-participants.js.map +1 -1
  20. package/lib/browser/core-preferences.js +1 -1
  21. package/lib/browser/core-preferences.js.map +1 -1
  22. package/lib/browser/endpoint.js +3 -3
  23. package/lib/browser/endpoint.js.map +1 -1
  24. package/lib/browser/keybinding.js +1 -1
  25. package/lib/browser/keybinding.js.map +1 -1
  26. package/lib/browser/label-provider.js +1 -1
  27. package/lib/browser/label-provider.js.map +1 -1
  28. package/lib/browser/preferences/preference-proxy.js +2 -2
  29. package/lib/browser/preferences/preference-proxy.js.map +1 -1
  30. package/lib/browser/quick-input/quick-command-frontend-contribution.d.ts.map +1 -1
  31. package/lib/browser/quick-input/quick-command-frontend-contribution.js +25 -1
  32. package/lib/browser/quick-input/quick-command-frontend-contribution.js.map +1 -1
  33. package/lib/browser/quick-input/quick-command-service.d.ts +1 -0
  34. package/lib/browser/quick-input/quick-command-service.d.ts.map +1 -1
  35. package/lib/browser/quick-input/quick-command-service.js +4 -1
  36. package/lib/browser/quick-input/quick-command-service.js.map +1 -1
  37. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts +2 -0
  38. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts.map +1 -1
  39. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +23 -8
  40. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -1
  41. package/lib/browser/tree/search-box-debounce.js +1 -1
  42. package/lib/browser/tree/search-box-debounce.js.map +1 -1
  43. package/lib/browser/view-container.d.ts +10 -0
  44. package/lib/browser/view-container.d.ts.map +1 -1
  45. package/lib/browser/view-container.js +15 -1
  46. package/lib/browser/view-container.js.map +1 -1
  47. package/lib/browser/widget-decoration.js +1 -1
  48. package/lib/browser/widget-decoration.js.map +1 -1
  49. package/lib/common/command.d.ts +1 -0
  50. package/lib/common/command.d.ts.map +1 -1
  51. package/lib/common/command.js.map +1 -1
  52. package/lib/common/glob.js +5 -5
  53. package/lib/common/glob.js.map +1 -1
  54. package/lib/common/index.d.ts +1 -0
  55. package/lib/common/index.d.ts.map +1 -1
  56. package/lib/common/index.js +1 -0
  57. package/lib/common/index.js.map +1 -1
  58. package/lib/common/objects.d.ts +1 -0
  59. package/lib/common/objects.d.ts.map +1 -1
  60. package/lib/common/objects.js +43 -1
  61. package/lib/common/objects.js.map +1 -1
  62. package/lib/common/path.js +9 -9
  63. package/lib/common/path.js.map +1 -1
  64. package/lib/common/paths.js +1 -1
  65. package/lib/common/paths.js.map +1 -1
  66. package/lib/common/severity.js +1 -1
  67. package/lib/common/severity.js.map +1 -1
  68. package/lib/common/telemetry.d.ts +20 -0
  69. package/lib/common/telemetry.d.ts.map +1 -0
  70. package/lib/common/telemetry.js +25 -0
  71. package/lib/common/telemetry.js.map +1 -0
  72. package/lib/electron-browser/menu/electron-main-menu-factory.d.ts +5 -0
  73. package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
  74. package/lib/electron-browser/menu/electron-main-menu-factory.js +4 -3
  75. package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
  76. package/lib/node/backend-application-module.d.ts.map +1 -1
  77. package/lib/node/backend-application-module.js +2 -0
  78. package/lib/node/backend-application-module.js.map +1 -1
  79. package/lib/node/filesystem-locking.d.ts +24 -0
  80. package/lib/node/filesystem-locking.d.ts.map +1 -0
  81. package/lib/node/filesystem-locking.js +71 -0
  82. package/lib/node/filesystem-locking.js.map +1 -0
  83. package/lib/node/index.d.ts +1 -0
  84. package/lib/node/index.d.ts.map +1 -1
  85. package/lib/node/index.js +3 -0
  86. package/lib/node/index.js.map +1 -1
  87. package/lib/node/messaging/ipc-connection-provider.js +1 -1
  88. package/lib/node/messaging/ipc-connection-provider.js.map +1 -1
  89. package/package.json +7 -6
  90. package/src/browser/common-frontend-contribution.ts +3 -3
  91. package/src/browser/common-styling-participants.ts +20 -0
  92. package/src/browser/core-preferences.ts +1 -1
  93. package/src/browser/endpoint.ts +3 -3
  94. package/src/browser/keybinding.ts +1 -1
  95. package/src/browser/label-provider.ts +1 -1
  96. package/src/browser/preferences/preference-proxy.ts +2 -2
  97. package/src/browser/quick-input/quick-command-frontend-contribution.ts +26 -2
  98. package/src/browser/quick-input/quick-command-service.ts +4 -0
  99. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +23 -6
  100. package/src/browser/tree/search-box-debounce.ts +1 -1
  101. package/src/browser/view-container.ts +21 -0
  102. package/src/browser/widget-decoration.ts +1 -1
  103. package/src/common/command.ts +1 -0
  104. package/src/common/glob.ts +5 -5
  105. package/src/common/i18n/nls.metadata.json +16592 -14032
  106. package/src/common/index.ts +1 -0
  107. package/src/common/objects.ts +48 -1
  108. package/src/common/path.ts +9 -9
  109. package/src/common/paths.ts +1 -1
  110. package/src/common/severity.ts +1 -1
  111. package/src/common/telemetry.ts +45 -0
  112. package/src/electron-browser/menu/electron-main-menu-factory.ts +10 -3
  113. package/src/node/backend-application-module.ts +3 -0
  114. package/src/node/filesystem-locking.ts +77 -0
  115. package/src/node/index.ts +1 -0
  116. package/src/node/messaging/ipc-connection-provider.ts +1 -1
@@ -46,4 +46,5 @@ export * from './strings';
46
46
  export * from './types';
47
47
  export { default as URI } from './uri';
48
48
  export * from './view-column';
49
+ export * from './telemetry';
49
50
 
@@ -14,7 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { isObject } from './types';
17
+ import { isObject, isUndefined } from './types';
18
18
 
19
19
  export function deepClone<T>(obj: T): T {
20
20
  if (!isObject(obj)) {
@@ -70,3 +70,50 @@ export function notEmpty<T>(arg: T | undefined | null): arg is T {
70
70
  export function isEmpty(arg: Object): boolean {
71
71
  return Object.keys(arg).length === 0 && arg.constructor === Object;
72
72
  }
73
+
74
+ // copied and modified from https://github.com/microsoft/vscode/blob/1.76.0/src/vs/base/common/objects.ts#L45-L83
75
+ /*---------------------------------------------------------------------------------------------
76
+ * Copyright (c) Microsoft Corporation. All rights reserved.
77
+ * Licensed under the MIT License. See License.txt in the project root for license information.
78
+ *--------------------------------------------------------------------------------------------*/
79
+
80
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
+ export function cloneAndChange(obj: any, changer: (orig: any) => any, seen: Set<any>): any {
82
+ // impossible to clone an undefined or null object
83
+ // eslint-disable-next-line no-null/no-null
84
+ if (isUndefined(obj) || obj === null) {
85
+ return obj;
86
+ }
87
+
88
+ const changed = changer(obj);
89
+ if (!isUndefined(changed)) {
90
+ return changed;
91
+ }
92
+
93
+ if (Array.isArray(obj)) {
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
+ const r1: any[] = [];
96
+ for (const e of obj) {
97
+ r1.push(cloneAndChange(e, changer, seen));
98
+ }
99
+ return r1;
100
+ }
101
+
102
+ if (isObject(obj)) {
103
+ if (seen.has(obj)) {
104
+ throw new Error('Cannot clone recursive data-structure');
105
+ }
106
+ seen.add(obj);
107
+ const r2 = {};
108
+ for (const i2 in obj) {
109
+ if (_hasOwnProperty.call(obj, i2)) {
110
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
+ (r2 as any)[i2] = cloneAndChange(obj[i2], changer, seen);
112
+ }
113
+ }
114
+ seen.delete(obj);
115
+ return r2;
116
+ }
117
+
118
+ return obj;
119
+ }
@@ -51,12 +51,12 @@ export class Path {
51
51
  if (path.length >= 3 && path.charCodeAt(0) === 47 /* '/' */ && path.charCodeAt(2) === 58 /* ':' */) {
52
52
  const code = path.charCodeAt(1);
53
53
  if (code >= 65 /* A */ && code <= 90 /* Z */) {
54
- path = `/${String.fromCharCode(code + 32)}:${path.substr(3)}`; // "/c:".length === 3
54
+ path = `/${String.fromCharCode(code + 32)}:${path.substring(3)}`; // "/c:".length === 3
55
55
  }
56
56
  } else if (path.length >= 2 && path.charCodeAt(1) === 58 /* ':' */) {
57
57
  const code = path.charCodeAt(0);
58
58
  if (code >= 65 /* A */ && code <= 90 /* Z */) {
59
- path = `${String.fromCharCode(code + 32)}:${path.substr(2)}`; // "c:".length === 2
59
+ path = `${String.fromCharCode(code + 32)}:${path.substring(2)}`; // "c:".length === 2
60
60
  }
61
61
  if (path.charCodeAt(0) !== 47 /* '/' */) {
62
62
  path = `${String.fromCharCode(47)}${path}`;
@@ -147,13 +147,13 @@ export class Path {
147
147
  const firstIndex = this.raw.indexOf(Path.separator);
148
148
  const lastIndex = this.raw.lastIndexOf(Path.separator);
149
149
  this.isAbsolute = firstIndex === 0;
150
- this.base = lastIndex === -1 ? this.raw : this.raw.substr(lastIndex + 1);
150
+ this.base = lastIndex === -1 ? this.raw : this.raw.substring(lastIndex + 1);
151
151
  this.isRoot = this.isAbsolute && firstIndex === lastIndex && (!this.base || Path.isDrive(this.base));
152
152
  this.root = this.computeRoot();
153
153
 
154
154
  const extIndex = this.base.lastIndexOf('.');
155
- this.name = extIndex === -1 ? this.base : this.base.substr(0, extIndex);
156
- this.ext = extIndex === -1 ? '' : this.base.substr(extIndex);
155
+ this.name = extIndex === -1 ? this.base : this.base.substring(0, extIndex);
156
+ this.ext = extIndex === -1 ? '' : this.base.substring(extIndex);
157
157
  }
158
158
 
159
159
  protected computeRoot(): Path | undefined {
@@ -173,7 +173,7 @@ export class Path {
173
173
  }
174
174
  // '/c:/foo/bar' -> '/c:'
175
175
  // '/foo/bar' -> '/'
176
- return new Path(this.raw.substr(0, index)).root;
176
+ return new Path(this.raw.substring(0, index)).root;
177
177
  }
178
178
 
179
179
  /**
@@ -204,10 +204,10 @@ export class Path {
204
204
  if (this.isAbsolute) {
205
205
  const firstIndex = this.raw.indexOf(Path.separator);
206
206
  if (firstIndex === lastIndex) {
207
- return new Path(this.raw.substr(0, firstIndex + 1));
207
+ return new Path(this.raw.substring(0, firstIndex + 1));
208
208
  }
209
209
  }
210
- return new Path(this.raw.substr(0, lastIndex));
210
+ return new Path(this.raw.substring(0, lastIndex));
211
211
  }
212
212
 
213
213
  join(...paths: string[]): Path {
@@ -274,7 +274,7 @@ export class Path {
274
274
  if (!path.raw.startsWith(raw)) {
275
275
  return undefined;
276
276
  }
277
- const relativePath = path.raw.substr(raw.length);
277
+ const relativePath = path.raw.substring(raw.length);
278
278
  return new Path(relativePath);
279
279
  }
280
280
 
@@ -55,7 +55,7 @@ export function basename(path: string): string {
55
55
  } else if (~idx === path.length - 1) {
56
56
  return basename(path.substring(0, path.length - 1));
57
57
  } else {
58
- return path.substr(~idx + 1);
58
+ return path.substring(~idx + 1);
59
59
  }
60
60
  }
61
61
 
@@ -101,7 +101,7 @@ export namespace Severity {
101
101
  } else if (severity === Severity.Log || severity === log) {
102
102
  return nls.localize('theia/core/severity/log', 'Log');
103
103
  } else {
104
- return nls.localize('theia/core/severity/all', 'All');
104
+ return nls.localizeByDefault('All');
105
105
  }
106
106
  }
107
107
 
@@ -0,0 +1,45 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 STMicroelectronics and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ export class TelemetryTrustedValue<T> {
18
+ readonly value: T;
19
+
20
+ constructor(value: T) {
21
+ this.value = value;
22
+ }
23
+ }
24
+
25
+ export interface TelemetryLogger {
26
+ readonly sender: TelemetrySender;
27
+ readonly options: TelemetryLoggerOptions | undefined;
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ logUsage(eventName: string, data?: Record<string, any | TelemetryTrustedValue<any>>): void;
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ logError(eventNameOrException: string | Error, data?: Record<string, any | TelemetryTrustedValue<any>>): void;
32
+
33
+ dispose(): void;
34
+ }
35
+
36
+ interface TelemetrySender {
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ sendEventData(eventName: string, data?: Record<string, any>): void;
39
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
+ sendErrorData(error: Error, data?: Record<string, any>): void;
41
+ flush?(): void | Thenable<void>;
42
+ }
43
+
44
+ interface TelemetryLoggerOptions {
45
+ }
@@ -35,6 +35,12 @@ export interface ElectronMenuOptions {
35
35
  * Defaults to `true`.
36
36
  */
37
37
  readonly showDisabled?: boolean;
38
+
39
+ /**
40
+ * Controls whether to render disabled items as disabled
41
+ * Defaults to `true`
42
+ */
43
+ readonly honorDisabled?: boolean;
38
44
  /**
39
45
  * A DOM context to use when evaluating any `when` clauses
40
46
  * of menu items registered for this item.
@@ -108,7 +114,7 @@ export class ElectronMainMenuFactory extends BrowserMainMenuFactory {
108
114
  const maxWidget = document.getElementsByClassName(MAXIMIZED_CLASS);
109
115
  if (preference === 'visible' || (preference === 'classic' && maxWidget.length === 0)) {
110
116
  const menuModel = this.menuProvider.getMenu(MAIN_MENU_BAR);
111
- this._menu = this.fillMenuTemplate([], menuModel, [], { rootMenuPath: MAIN_MENU_BAR });
117
+ this._menu = this.fillMenuTemplate([], menuModel, [], { honorDisabled: false, rootMenuPath: MAIN_MENU_BAR });
112
118
  if (isOSX) {
113
119
  this._menu.unshift(this.createOSXMenu());
114
120
  }
@@ -121,7 +127,7 @@ export class ElectronMainMenuFactory extends BrowserMainMenuFactory {
121
127
 
122
128
  createElectronContextMenu(menuPath: MenuPath, args?: any[], context?: HTMLElement, contextKeyService?: ContextMatcher): MenuDto[] {
123
129
  const menuModel = this.menuProvider.getMenu(menuPath);
124
- return this.fillMenuTemplate([], menuModel, args, { showDisabled: false, context, rootMenuPath: menuPath, contextKeyService });
130
+ return this.fillMenuTemplate([], menuModel, args, { showDisabled: true, context, rootMenuPath: menuPath, contextKeyService });
125
131
  }
126
132
 
127
133
  protected fillMenuTemplate(parentItems: MenuDto[],
@@ -130,6 +136,7 @@ export class ElectronMainMenuFactory extends BrowserMainMenuFactory {
130
136
  options: ElectronMenuOptions
131
137
  ): MenuDto[] {
132
138
  const showDisabled = options?.showDisabled !== false;
139
+ const honorDisabled = options?.honorDisabled !== false;
133
140
 
134
141
  if (CompoundMenuNode.is(menu) && menu.children.length && this.undefinedOrMatch(options.contextKeyService ?? this.contextKeyService, menu.when, options.context)) {
135
142
  const role = CompoundMenuNode.getRole(menu);
@@ -181,7 +188,7 @@ export class ElectronMainMenuFactory extends BrowserMainMenuFactory {
181
188
  label: node.label,
182
189
  type: this.commandRegistry.getToggledHandler(commandId, ...args) ? 'checkbox' : 'normal',
183
190
  checked: this.commandRegistry.isToggled(commandId, ...args),
184
- enabled: true, // https://github.com/eclipse-theia/theia/issues/446
191
+ enabled: !honorDisabled || this.commandRegistry.isEnabled(commandId, ...args), // see https://github.com/eclipse-theia/theia/issues/446
185
192
  visible: true,
186
193
  accelerator,
187
194
  execute: () => this.execute(commandId, args, options.rootMenuPath)
@@ -40,6 +40,7 @@ import { ProxyCliContribution } from './request/proxy-cli-contribution';
40
40
  import { bindNodeStopwatch, bindBackendStopwatchServer } from './performance';
41
41
  import { OSBackendApplicationContribution } from './os-backend-application-contribution';
42
42
  import { BackendRequestFacade } from './request/backend-request-facade';
43
+ import { FileSystemLocking, FileSystemLockingImpl } from './filesystem-locking';
43
44
 
44
45
  decorate(injectable(), ApplicationPackage);
45
46
 
@@ -128,4 +129,6 @@ export const backendApplicationModule = new ContainerModule(bind => {
128
129
 
129
130
  bindNodeStopwatch(bind);
130
131
  bindBackendStopwatchServer(bind);
132
+
133
+ bind(FileSystemLocking).to(FileSystemLockingImpl).inSingletonScope();
131
134
  });
@@ -0,0 +1,77 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 Ericsson and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { Mutex } from 'async-mutex';
18
+ import { injectable, interfaces } from 'inversify';
19
+ import * as path from 'path';
20
+
21
+ export const FileSystemLocking = Symbol('FileSystemLocking') as symbol & interfaces.Abstract<FileSystemLocking>;
22
+ /**
23
+ * Use this backend service to help prevent race access to files on disk.
24
+ */
25
+ export interface FileSystemLocking {
26
+ /**
27
+ * Get exclusive access to a file for reading and/or writing.
28
+ * @param lockPath The path to request exclusive access to.
29
+ * @param transaction The job to do while having exclusive access.
30
+ * @param thisArg `this` argument used when calling `transaction`.
31
+ */
32
+ lockPath<T>(lockPath: string, transaction: (lockPath: string) => T | Promise<T>, thisArg?: unknown): Promise<T>;
33
+ }
34
+
35
+ @injectable()
36
+ export class FileSystemLockingImpl implements FileSystemLocking {
37
+
38
+ lockPath<T>(lockPath: string, transaction: (lockPath: string) => T | Promise<T>, thisArg?: unknown): Promise<T> {
39
+ const resolvedLockPath = this.resolveLockPath(lockPath);
40
+ return this.getLock(resolvedLockPath).runExclusive(async () => transaction.call(thisArg, resolvedLockPath));
41
+ }
42
+
43
+ protected resolveLockPath(lockPath: string): string {
44
+ // try to normalize the path to avoid two paths pointing to the same file
45
+ return path.resolve(lockPath);
46
+ }
47
+
48
+ protected getLocks(): Map<string, Mutex> {
49
+ const kLocks = Symbol.for('FileSystemLockingImpl.Locks');
50
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
+ return (globalThis as any)[kLocks] ??= this.initializeLocks();
52
+ }
53
+
54
+ protected initializeLocks(): Map<string, Mutex> {
55
+ const locks = new Map();
56
+ const cleanup = setInterval(() => this.cleanupLocks(locks), 60_000);
57
+ process.once('beforeExit', () => clearInterval(cleanup));
58
+ return locks;
59
+ }
60
+
61
+ protected cleanupLocks(locks: Map<string, Mutex>): void {
62
+ locks.forEach((lock, lockPath) => {
63
+ if (!lock.isLocked()) {
64
+ locks.delete(lockPath);
65
+ }
66
+ });
67
+ }
68
+
69
+ protected getLock(lockPath: string): Mutex {
70
+ const locks = this.getLocks();
71
+ let lock = locks.get(lockPath);
72
+ if (!lock) {
73
+ locks.set(lockPath, lock = new Mutex());
74
+ }
75
+ return lock;
76
+ }
77
+ }
package/src/node/index.ts CHANGED
@@ -19,3 +19,4 @@ export * from './debug';
19
19
  export * from './file-uri';
20
20
  export * from './messaging';
21
21
  export * from './cli';
22
+ export { FileSystemLocking } from './filesystem-locking';
@@ -90,7 +90,7 @@ export class IPCConnectionProvider {
90
90
  const inspectArgPrefix = `--${options.serverName}-inspect`;
91
91
  const inspectArg = process.argv.find(v => v.startsWith(inspectArgPrefix));
92
92
  if (inspectArg !== undefined) {
93
- forkOptions.execArgv = ['--nolazy', `--inspect${inspectArg.substr(inspectArgPrefix.length)}`];
93
+ forkOptions.execArgv = ['--nolazy', `--inspect${inspectArg.substring(inspectArgPrefix.length)}`];
94
94
  }
95
95
 
96
96
  const childProcess = cp.fork(path.join(__dirname, 'ipc-bootstrap'), options.args, forkOptions);