Skip to content

Commit e60b1cd

Browse files
test
Signed-off-by: Roman Nikitenko <rnikiten@redhat.com>
1 parent a74ab58 commit e60b1cd

2 files changed

Lines changed: 93 additions & 27 deletions

File tree

code/extensions/che-api/src/extension.ts

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import type { TelemetryService } from './api/telemetry-service';
2626

2727
const NAVIGATOR_DIAG_PREFIX = '[che-api][navigator-diag]';
2828
const ENABLE_NAVIGATOR_DIAGNOSTICS = process.env.CHE_API_NAVIGATOR_DIAGNOSTICS !== 'false';
29+
const IMPORT_STRATEGY = process.env.CHE_API_IMPORT_STRATEGY === 'eager' ? 'eager' : 'lazy';
2930

3031
type DependencyProbe = {
3132
moduleName: string;
@@ -80,9 +81,59 @@ async function runNavigatorDependencyDiagnostics(): Promise<void> {
8081
console.info(`${NAVIGATOR_DIAG_PREFIX} diagnostics completed`);
8182
}
8283

84+
function importAxiosModule() {
85+
return import('axios');
86+
}
87+
88+
type LoadedExtensionModules = [
89+
Awaited<ReturnType<typeof importAxiosModule>>,
90+
typeof import('./api/devfile-service'),
91+
typeof import('./api/k8s-service'),
92+
typeof import('./impl/k8s-devfile-service-impl'),
93+
typeof import('./impl/k8s-service-impl'),
94+
typeof import('./impl/k8s-devworkspace-env-variables'),
95+
typeof import('./api/workspace-service'),
96+
typeof import('./impl/k8s-workspace-service-impl'),
97+
typeof import('./api/github-service'),
98+
typeof import('./impl/github-service-impl'),
99+
typeof import('./api/telemetry-service'),
100+
typeof import('./impl/k8s-telemetry-service-impl'),
101+
typeof import('./logger')
102+
];
103+
104+
async function loadExtensionModules(): Promise<LoadedExtensionModules> {
105+
return Promise.all([
106+
importAxiosModule(),
107+
import('./api/devfile-service'),
108+
import('./api/k8s-service'),
109+
import('./impl/k8s-devfile-service-impl'),
110+
import('./impl/k8s-service-impl'),
111+
import('./impl/k8s-devworkspace-env-variables'),
112+
import('./api/workspace-service'),
113+
import('./impl/k8s-workspace-service-impl'),
114+
import('./api/github-service'),
115+
import('./impl/github-service-impl'),
116+
import('./api/telemetry-service'),
117+
import('./impl/k8s-telemetry-service-impl'),
118+
import('./logger')
119+
]);
120+
}
121+
83122

84123
export async function activate(_extensionContext: vscode.ExtensionContext): Promise<Api> {
85-
await runNavigatorDependencyDiagnostics();
124+
console.info(`${NAVIGATOR_DIAG_PREFIX} import strategy: ${IMPORT_STRATEGY}`);
125+
let loadedModules: LoadedExtensionModules;
126+
127+
if (IMPORT_STRATEGY === 'eager') {
128+
const preloadStart = Date.now();
129+
console.info(`${NAVIGATOR_DIAG_PREFIX} START eager preload`);
130+
loadedModules = await loadExtensionModules();
131+
console.info(`${NAVIGATOR_DIAG_PREFIX} DONE eager preload in ${Date.now() - preloadStart}ms`);
132+
await runNavigatorDependencyDiagnostics();
133+
} else {
134+
await runNavigatorDependencyDiagnostics();
135+
loadedModules = await loadExtensionModules();
136+
}
86137

87138
const [
88139
axiosModule,
@@ -98,21 +149,7 @@ export async function activate(_extensionContext: vscode.ExtensionContext): Prom
98149
{ TelemetryService },
99150
{ K8sTelemetryServiceImpl },
100151
{ Logger }
101-
] = await Promise.all([
102-
import('axios'),
103-
import('./api/devfile-service'),
104-
import('./api/k8s-service'),
105-
import('./impl/k8s-devfile-service-impl'),
106-
import('./impl/k8s-service-impl'),
107-
import('./impl/k8s-devworkspace-env-variables'),
108-
import('./api/workspace-service'),
109-
import('./impl/k8s-workspace-service-impl'),
110-
import('./api/github-service'),
111-
import('./impl/github-service-impl'),
112-
import('./api/telemetry-service'),
113-
import('./impl/k8s-telemetry-service-impl'),
114-
import('./logger')
115-
]);
152+
] = loadedModules;
116153

117154
const container = new Container();
118155
container.bind(K8sDevfileServiceImpl).toSelf().inSingletonScope();
@@ -121,7 +158,8 @@ export async function activate(_extensionContext: vscode.ExtensionContext): Prom
121158
container.bind(K8SServiceImpl).toSelf().inSingletonScope();
122159
container.bind(K8SService).to(K8SServiceImpl).inSingletonScope();
123160
container.bind(K8sDevWorkspaceEnvVariables).toSelf().inSingletonScope();
124-
container.bind(Symbol.for('AxiosInstance')).toConstantValue(axiosModule);
161+
const axiosRuntime = (axiosModule as { default?: unknown }).default ?? axiosModule;
162+
container.bind(Symbol.for('AxiosInstance')).toConstantValue(axiosRuntime);
125163
container.bind(GithubServiceImpl).toSelf().inSingletonScope();
126164
container.bind(GithubService).to(GithubServiceImpl).inSingletonScope();
127165
container.bind(TelemetryService).to(K8sTelemetryServiceImpl).inSingletonScope();

code/src/vs/workbench/api/node/extensionHostProcess.ts

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,50 @@ const args = minimist(process.argv.slice(2), {
8181
(function () {
8282
const Module = require('module');
8383
const originalLoad = Module._load;
84+
const maxNavigatorDiagLogs = 20;
85+
let pendingNavigatorDiagCount = 0;
86+
let hasLoggedNavigatorDiagSuppression = false;
87+
let lastModuleLoadRequest: string | undefined;
88+
let lastModuleLoadParent: string | undefined;
89+
90+
Module._load = function (request: string, parent: { id?: string; filename?: string } | undefined) {
91+
const prevRequest = lastModuleLoadRequest;
92+
const prevParent = lastModuleLoadParent;
93+
lastModuleLoadRequest = request;
94+
lastModuleLoadParent = parent?.filename ?? parent?.id;
8495

85-
Module._load = function (request: string) {
8696
if (request === 'natives') {
8797
throw new Error('Either the extension or an NPM dependency is using the [unsupported "natives" node module](https://go.microsoft.com/fwlink/?linkid=871887).');
8898
}
8999

90-
return originalLoad.apply(this, arguments);
100+
try {
101+
return originalLoad.apply(this, arguments);
102+
} finally {
103+
lastModuleLoadRequest = prevRequest;
104+
lastModuleLoadParent = prevParent;
105+
}
91106
};
107+
108+
if (!args.supportGlobalNavigator) {
109+
Object.defineProperty(globalThis, 'navigator', {
110+
get: () => {
111+
onUnexpectedExternalError(new PendingMigrationError('navigator is now a global in nodejs, please see https://aka.ms/vscode-extensions/navigator for additional info on this error.'));
112+
pendingNavigatorDiagCount++;
113+
114+
if (pendingNavigatorDiagCount <= maxNavigatorDiagLogs) {
115+
const stack = new Error().stack?.split('\n').slice(2, 8).join('\n');
116+
console.warn(`[pending-migration][navigator] access #${pendingNavigatorDiagCount}; lastModule="${lastModuleLoadRequest ?? 'unknown'}"; parent="${lastModuleLoadParent ?? 'unknown'}"`);
117+
if (stack) {
118+
console.warn(`[pending-migration][navigator] stack:\n${stack}`);
119+
}
120+
} else if (!hasLoggedNavigatorDiagSuppression) {
121+
hasLoggedNavigatorDiagSuppression = true;
122+
console.warn(`[pending-migration][navigator] additional accesses suppressed after ${maxNavigatorDiagLogs} logs`);
123+
}
124+
return undefined;
125+
}
126+
});
127+
}
92128
})();
93129

94130
// custom process.exit logic...
@@ -139,14 +175,6 @@ function patchProcess(allowExit: boolean) {
139175

140176
// NodeJS since v21 defines navigator as a global object. This will likely surprise many extensions and potentially break them
141177
// because `navigator` has historically often been used to check if running in a browser (vs running inside NodeJS)
142-
if (!args.supportGlobalNavigator) {
143-
Object.defineProperty(globalThis, 'navigator', {
144-
get: () => {
145-
onUnexpectedExternalError(new PendingMigrationError('navigator is now a global in nodejs, please see https://aka.ms/vscode-extensions/navigator for additional info on this error.'));
146-
return undefined;
147-
}
148-
});
149-
}
150178

151179

152180
interface IRendererConnection {

0 commit comments

Comments
 (0)