Path: blob/main/test/smoke/extensions/vscode-smoketest-ext-host/extension.js
5334 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45// @ts-check6const vscode = require('vscode');7const fs = require('fs');8const path = require('path');9const os = require('os');1011/** @type {string | undefined} */12let deactivateMarkerFile;1314/**15* @param {vscode.ExtensionContext} context16*/17function activate(context) {18// This is used to verify that the extension host process is properly killed19// when window reloads even if the extension host is blocked20// Refs: https://github.com/microsoft/vscode/issues/29134621context.subscriptions.push(22vscode.commands.registerCommand('smoketest.getExtensionHostPidAndBlock', (delayMs = 100, durationMs = 60000) => {23const pid = process.pid;2425// Write PID file to workspace folder if available, otherwise temp dir26// Note: filename must match name in extension-host-restart.test.ts27const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;28const pidFile = workspaceFolder29? path.join(workspaceFolder, 'vscode-ext-host-pid.txt')30: path.join(os.tmpdir(), 'vscode-ext-host-pid.txt');31setTimeout(() => {32fs.writeFileSync(pidFile, String(pid), 'utf-8');3334// Block the extension host without busy-spinning to avoid pegging a CPU core.35// Prefer Atomics.wait on a SharedArrayBuffer when available; otherwise, fall back36// to the original busy loop to preserve behavior in older environments.37if (typeof SharedArrayBuffer === 'function' && typeof Atomics !== 'undefined' && typeof Atomics.wait === 'function') {38const sab = new SharedArrayBuffer(4);39const blocker = new Int32Array(sab);40// Wait up to durationMs milliseconds. This blocks the thread without consuming CPU.41Atomics.wait(blocker, 0, 0, durationMs);42} else {43const start = Date.now();44while (Date.now() - start < durationMs) {45// Busy loop (fallback)46}47}48}, delayMs);4950return pid;51})52);5354// This command sets up a marker file path that will be written during deactivation.55// It allows the smoke test to verify that extensions get a chance to deactivate.56context.subscriptions.push(57vscode.commands.registerCommand('smoketest.setupGracefulDeactivation', () => {58const pid = process.pid;59const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;60const pidFile = workspaceFolder61? path.join(workspaceFolder, 'vscode-ext-host-pid-graceful.txt')62: path.join(os.tmpdir(), 'vscode-ext-host-pid-graceful.txt');63deactivateMarkerFile = workspaceFolder64? path.join(workspaceFolder, 'vscode-ext-host-deactivated.txt')65: path.join(os.tmpdir(), 'vscode-ext-host-deactivated.txt');6667// Write PID file immediately so test knows the extension is ready68fs.writeFileSync(pidFile, String(pid), 'utf-8');6970return { pid, markerFile: deactivateMarkerFile };71})72);73}7475function deactivate() {76// Write marker file to indicate deactivation was called77if (deactivateMarkerFile) {78try {79fs.writeFileSync(deactivateMarkerFile, `deactivated at ${Date.now()}`, 'utf-8');80} catch {81// Ignore errors (e.g., folder not accessible)82}83}84}8586module.exports = {87activate,88deactivate89};909192