From a068517e8db972470a762b7c8c5c2ae8f65d07a3 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 25 Jul 2022 11:32:02 +1000 Subject: [PATCH 01/10] Ensure the extension loads in the `Safari` browser --- build/ci/postInstall.js | 72 ++++++++++++++++++ build/launchWeb.js | 6 ++ build/launchWebTest.js | 58 +------------- build/launchWebUtils.js | 75 +++++++++++++++++++ news/2 Fixes/10621.md | 1 + package.json | 3 +- .../baseIPyWidgetScriptManager.ts | 2 +- 7 files changed, 159 insertions(+), 58 deletions(-) create mode 100644 build/launchWeb.js create mode 100644 build/launchWebUtils.js create mode 100644 news/2 Fixes/10621.md diff --git a/build/ci/postInstall.js b/build/ci/postInstall.js index a1225de8caa..36164590440 100644 --- a/build/ci/postInstall.js +++ b/build/ci/postInstall.js @@ -8,6 +8,7 @@ const fs = require('fs-extra'); const path = require('path'); const constants = require('../constants'); const child_process = require('child_process'); +const dedent = require('dedent'); /** * In order to get raw kernels working, we reuse the default kernel that jupyterlab ships. @@ -125,7 +126,78 @@ function fixJupyterLabRenderers() { } } +function fixJupyterLabFuture() { + const warnings = []; + [ + 'node_modules/@jupyterlab/services/lib/kernel/future.js', + 'node_modules/@lumino/signaling/dist/index.es6.js' + ].forEach((file) => { + const filePath = path.join(__dirname, '..', '..', file); + if (!fs.existsSync(filePath)) { + return; + } + const textToReplace = `return ok ? requestAnimationFrame : setImmediate;`; + const textToReplaceWith = `return ok ? requestAnimationFrame : (typeof setImmediate === 'function' ? setImmediate : setTimeout);`; + const fileContents = fs.readFileSync(filePath, 'utf8').toString(); + if (fileContents.indexOf(textToReplace) === -1 && fileContents.indexOf(textToReplaceWith) === -1) { + warnings.push(`Unable to find Jupyter kernel/future/setImmediate usage to replace! in ${file}`); + } + fs.writeFileSync(filePath, fileContents.replace(textToReplace, textToReplaceWith)); + }); + if (warnings.length === 2) { + throw new Error(warnings[0] + '\n' + warnings[1]); + } +} +function fixLuminoPolling() { + const warnings = []; + ['node_modules/@lumino/polling/dist/index.es6.js'].forEach((file) => { + const filePath = path.join(__dirname, '..', '..', file); + if (!fs.existsSync(filePath)) { + return; + } + const textToReplace = `: setImmediate;`; + const textToReplaceWith = `: typeof setImmediate === 'function' ? setImmediate : setTimeout;`; + const fileContents = fs.readFileSync(filePath, 'utf8').toString(); + if (fileContents.indexOf(textToReplace) === -1 && fileContents.indexOf(textToReplaceWith) === -1) { + warnings.push('Unable to find Jupyter @lumino/polling/setImmediate usage to replace!'); + } + fs.writeFileSync(filePath, fileContents.replace(textToReplace, textToReplaceWith)); + + const textToReplace2 = `: clearImmediate;`; + const textToReplaceWith2 = `: typeof clearImmediate === 'function' ? clearImmediate : clearTimeout;`; + const fileContents2 = fs.readFileSync(filePath, 'utf8').toString(); + if (fileContents2.indexOf(textToReplace2) === -1 && fileContents2.indexOf(textToReplaceWith2) === -1) { + warnings.push('Unable to find Jupyter @lumino/polling/clearImmediate usage to replace!'); + } + fs.writeFileSync(filePath, fileContents2.replace(textToReplace2, textToReplaceWith2)); + }); + if (warnings.length === 2) { + throw new Error(warnings[0] + '\n' + warnings[1]); + } +} + +function fixStripComments() { + const file = 'node_modules/strip-comments/lib/languages.js'; + const filePath = path.join(__dirname, '..', '..', file); + if (!fs.existsSync(filePath)) { + return; + } + const contents = dedent` + 'use strict'; + + exports.python = { + BLOCK_OPEN_REGEX: /^"""/, + BLOCK_CLOSE_REGEX: /^"""/, + LINE_REGEX: /^#.*/ + }; + `; + fs.writeFileSync(filePath, contents); +} + fixJupyterLabRenderers(); makeVariableExplorerAlwaysSorted(); createJupyterKernelWithoutSerialization(); updateJSDomTypeDefinition(); +fixJupyterLabFuture(); +fixLuminoPolling(); +fixStripComments(); diff --git a/build/launchWeb.js b/build/launchWeb.js new file mode 100644 index 00000000000..75776ee01f7 --- /dev/null +++ b/build/launchWeb.js @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +const { launch } = require('./launchWebUtils'); + +void launch(); diff --git a/build/launchWebTest.js b/build/launchWebTest.js index 83c9f9530b9..30e25d8d7e9 100644 --- a/build/launchWebTest.js +++ b/build/launchWebTest.js @@ -1,60 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -const path = require('path'); -const fs = require('fs-extra'); -const test_web = require('@vscode/test-web'); -const { startJupyter } = require('./preLaunchWebTest'); -const jsonc = require('jsonc-parser'); -const { startReportServer } = require('./webTestReporter'); -const { noop } = require('../out/test/core'); -const { isCI } = require('./constants'); -const extensionDevelopmentPath = path.resolve(__dirname, '../'); -const packageJsonFile = path.join(extensionDevelopmentPath, 'package.json'); +const { launch } = require('./launchWebUtils'); -async function go() { - let exitCode = 0; - let server; - let testServer; - try { - server = (await startJupyter()).server; - testServer = await startReportServer(); - const bundlePath = path.join(extensionDevelopmentPath, 'out', 'extension.web.bundle'); - - // Changing the logging level to be read from workspace settings file. - // This way we can enable verbose logging and get the logs for web tests. - const settingsJson = fs.readFileSync(packageJsonFile).toString(); - const edits = jsonc.modify( - settingsJson, - ['contributes', 'configuration', 'properties', 'jupyter.logging.level', 'scope'], - 'resource', - {} - ); - const updatedSettingsJson = jsonc.applyEdits(settingsJson, edits); - fs.writeFileSync(packageJsonFile, updatedSettingsJson); - - // Now run the test - await test_web.runTests({ - browserType: 'chromium', - verbose: true, - headless: isCI ? false : true, // Set this to false to debug failures (false on CI to support capturing screenshots when tests fail). - extensionDevelopmentPath, - folderPath: path.resolve(__dirname, '..', 'src', 'test', 'datascience'), - extensionTestsPath: bundlePath - }); - } catch (err) { - console.error('Failed to run tests', err); - exitCode = 1; - } finally { - if (testServer) { - await testServer.dispose().catch(noop); - } - if (server) { - await server.dispose(); - } - } - - // Not all promises complete. Force exit - process.exit(exitCode); -} -void go(); +void launch(true); diff --git a/build/launchWebUtils.js b/build/launchWebUtils.js new file mode 100644 index 00000000000..9884cc90d3e --- /dev/null +++ b/build/launchWebUtils.js @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +const path = require('path'); +const fs = require('fs-extra'); +const test_web = require('@vscode/test-web'); +const { startJupyter } = require('./preLaunchWebTest'); +const jsonc = require('jsonc-parser'); +const { startReportServer } = require('./webTestReporter'); +const { noop } = require('../out/test/core'); +const { isCI } = require('./constants'); +const extensionDevelopmentPath = path.resolve(__dirname, '../'); +const packageJsonFile = path.join(extensionDevelopmentPath, 'package.json'); +const yargs = require('yargs/yargs'); +const { hideBin } = require('yargs/helpers'); +const argv = yargs(hideBin(process.argv)).argv; + +const browserType = argv.browser || argv.browserType || 'chromimum'; + +exports.launch = async function launch(launchTests) { + let exitCode = 0; + let server; + let testServer; + try { + if (launchTests){ + server = (await startJupyter()).server; + testServer = await startReportServer(); + } + const bundlePath = path.join(extensionDevelopmentPath, 'out', 'extension.web.bundle'); + + // Changing the logging level to be read from workspace settings file. + // This way we can enable verbose logging and get the logs for web tests. + const settingsJson = fs.readFileSync(packageJsonFile).toString(); + const edits = jsonc.modify( + settingsJson, + ['contributes', 'configuration', 'properties', 'jupyter.logging.level', 'scope'], + 'resource', + {} + ); + const updatedSettingsJson = jsonc.applyEdits(settingsJson, edits); + fs.writeFileSync(packageJsonFile, updatedSettingsJson); + + if (launchTests) { + await test_web.runTests({ + browserType, + verbose: true, + headless: isCI ? false : false, // Set this to false to debug failures (false on CI to support capturing screenshots when tests fail). + extensionDevelopmentPath, + folderPath: path.resolve(__dirname, '..', 'src', 'test', 'datascience'), + extensionTestsPath: bundlePath + }); + } else { + await test_web.open({ + browserType, + verbose: true, + headless: false, + extensionDevelopmentPath, + folderPath: path.resolve(__dirname, '..', 'src', 'test', 'datascience') + }); + } + } catch (err) { + console.error(launchTests ? 'Failed to run tests' : 'Failed to launch VS Code', err); + exitCode = 1; + } finally { + if (testServer) { + await testServer.dispose().catch(noop); + } + if (server) { + await server.dispose(); + } + } + + // Not all promises complete. Force exit + process.exit(exitCode); +}; diff --git a/news/2 Fixes/10621.md b/news/2 Fixes/10621.md new file mode 100644 index 00000000000..1e0f4b71eb7 --- /dev/null +++ b/news/2 Fixes/10621.md @@ -0,0 +1 @@ +Ensure the extension loads in the `Safari` browser. diff --git a/package.json b/package.json index 8f0f14a33d1..0fc45c2da0a 100644 --- a/package.json +++ b/package.json @@ -2159,7 +2159,7 @@ "interactiveWindow" ], "scripts": { - "package": "gulp clean && gulp prePublishBundle && vsce package -o ms-toolsai-jupyter-insiders.vsix", + "package": "gulp clean && gulp prePublishBundle && vsce package -o ms-toolsai-jupyter-insiders.vsix", "packagePreRelease": "gulp clean && gulp prePublishBundle && vsce package --pre-release -o ms-toolsai-jupyter-insiders.vsix", "prePublishBundleNLS": "cross-env BUILD_WITH_VSCODE_NLS=true gulp prePublishBundle", "prePublishNonBundle": "gulp clean && gulp prePublishNonBundle", @@ -2195,6 +2195,7 @@ "testNativeNotebooksWithoutPythonInVSCode": "cross-env CODE_TESTS_WORKSPACE=src/test/datascience VSC_JUPYTER_CI_TEST_VSC_CHANNEL=insiders TEST_FILES_SUFFIX=*.vscode.test,*.vscode.common.test VSC_JUPYTER_FORCE_LOGGING=1 VSC_JUPYTER_LOAD_EXPERIMENTS_FROM_FILE=true VSC_JUPYTER_CI_TEST_GREP=non-python-kernel VSC_JUPYTER_CI_TEST_DO_NOT_INSTALL_PYTHON_EXT=true node ./out/test/testBootstrap.node.js ./out/test/standardTest.node.js", "testNativeNotebooksAndWebviews": "cross-env CODE_TESTS_WORKSPACE=src/test/datascience VSC_JUPYTER_CI_TEST_VSC_CHANNEL=insiders TEST_FILES_SUFFIX=*.vscode.test,*.vscode.common.test VSC_JUPYTER_FORCE_LOGGING=1 VSC_JUPYTER_CI_TEST_GREP=webview-test VSC_JUPYTER_LOAD_EXPERIMENTS_FROM_FILE=true node ./out/test/testBootstrap.node.js ./out/test/standardTest.node.js", "testWebExtension": "node ./build/launchWebTest.js", + "launchWebExtension": "node ./build/launchWeb.js", "testPerformance": "node ./out/test/perfTest.node.js", "testSmoke": "node ./out/test/testBootstrap.node.js ./out/test/smokeTest.node.js", "testSmokeLogged": "cross-env VSC_JUPYTER_FORCE_LOGGING=true VSC_JUPYTER_LOG_FILE=smoke-test.log node --no-force-async-hooks-checks ./out/test/testBootstrap.node.js ./out/test/smokeTest.node.js", diff --git a/src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.ts b/src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.ts index b0f9100eb64..6e23d30091c 100644 --- a/src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.ts +++ b/src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.ts @@ -66,7 +66,7 @@ export function extractRequireConfigFromWidgetEntry(baseUrl: Uri, widgetFolderNa // the config entry is js, and not json. // We cannot eval as thats dangerous, and we cannot use JSON.parse either as it not JSON. // Lets just extract what we need. - configStr = stripComments(configStr); + configStr = stripComments(configStr, { language: 'python' }); configStr = configStr.splitLines({ trim: true, removeEmptyEntries: true }).join(''); // Now that we have just valid JS, extract contents between the third '{' and corresponding ending '}' const mappings = configStr From a0ffce8fd2dc5e420ff876102809684013ee4022 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 25 Jul 2022 11:32:34 +1000 Subject: [PATCH 02/10] Misc --- build/launchWebUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/launchWebUtils.js b/build/launchWebUtils.js index 9884cc90d3e..0197417e377 100644 --- a/build/launchWebUtils.js +++ b/build/launchWebUtils.js @@ -22,7 +22,7 @@ exports.launch = async function launch(launchTests) { let server; let testServer; try { - if (launchTests){ + if (launchTests) { server = (await startJupyter()).server; testServer = await startReportServer(); } From 5afc17958fcd72195d121c442ce71a7abe5b42cb Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 25 Jul 2022 11:50:23 +1000 Subject: [PATCH 03/10] Misc --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0fc45c2da0a..42e7dc41849 100644 --- a/package.json +++ b/package.json @@ -2159,7 +2159,7 @@ "interactiveWindow" ], "scripts": { - "package": "gulp clean && gulp prePublishBundle && vsce package -o ms-toolsai-jupyter-insiders.vsix", + "package": "gulp clean && gulp prePublishBundle && vsce package -o ms-toolsai-jupyter-insiders.vsix", "packagePreRelease": "gulp clean && gulp prePublishBundle && vsce package --pre-release -o ms-toolsai-jupyter-insiders.vsix", "prePublishBundleNLS": "cross-env BUILD_WITH_VSCODE_NLS=true gulp prePublishBundle", "prePublishNonBundle": "gulp clean && gulp prePublishNonBundle", From b27a01536dc0e9e8fa4bd6a461bc8f0885c2ae11 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 25 Jul 2022 12:13:24 +1000 Subject: [PATCH 04/10] Fixes --- build/ci/postInstall.js | 15 +++++----- build/launchWebUtils.js | 29 +++++++------------ .../baseIPyWidgetScriptManager.ts | 2 +- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/build/ci/postInstall.js b/build/ci/postInstall.js index 36164590440..a4c6e5e9d87 100644 --- a/build/ci/postInstall.js +++ b/build/ci/postInstall.js @@ -182,15 +182,14 @@ function fixStripComments() { if (!fs.existsSync(filePath)) { return; } - const contents = dedent` - 'use strict'; + const contents = ` +'use strict'; - exports.python = { - BLOCK_OPEN_REGEX: /^"""/, - BLOCK_CLOSE_REGEX: /^"""/, - LINE_REGEX: /^#.*/ - }; - `; +exports.javascript = { + BLOCK_OPEN_REGEX: /^\\/\\*\\*?(!?)/, + BLOCK_CLOSE_REGEX: /^\\*\\/(\\n?)/, + LINE_REGEX: /^\\/\\/(!?).*/ +};`; fs.writeFileSync(filePath, contents); } diff --git a/build/launchWebUtils.js b/build/launchWebUtils.js index 0197417e377..68270c761d5 100644 --- a/build/launchWebUtils.js +++ b/build/launchWebUtils.js @@ -15,7 +15,7 @@ const yargs = require('yargs/yargs'); const { hideBin } = require('yargs/helpers'); const argv = yargs(hideBin(process.argv)).argv; -const browserType = argv.browser || argv.browserType || 'chromimum'; +const browserType = argv.browser || argv.browserType || 'chromium'; exports.launch = async function launch(launchTests) { let exitCode = 0; @@ -39,25 +39,18 @@ exports.launch = async function launch(launchTests) { ); const updatedSettingsJson = jsonc.applyEdits(settingsJson, edits); fs.writeFileSync(packageJsonFile, updatedSettingsJson); - + const options = { + browserType, + verbose: true, + headless: isCI ? false : false, // Set this to false to debug failures (false on CI to support capturing screenshots when tests fail). + extensionDevelopmentPath, + folderPath: path.resolve(__dirname, '..', 'src', 'test', 'datascience'), + extensionTestsPath: bundlePath + }; if (launchTests) { - await test_web.runTests({ - browserType, - verbose: true, - headless: isCI ? false : false, // Set this to false to debug failures (false on CI to support capturing screenshots when tests fail). - extensionDevelopmentPath, - folderPath: path.resolve(__dirname, '..', 'src', 'test', 'datascience'), - extensionTestsPath: bundlePath - }); - } else { - await test_web.open({ - browserType, - verbose: true, - headless: false, - extensionDevelopmentPath, - folderPath: path.resolve(__dirname, '..', 'src', 'test', 'datascience') - }); + options.extensionTestsPath = bundlePath; } + await test_web.runTests(options); } catch (err) { console.error(launchTests ? 'Failed to run tests' : 'Failed to launch VS Code', err); exitCode = 1; diff --git a/src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.ts b/src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.ts index 6e23d30091c..26787053132 100644 --- a/src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.ts +++ b/src/notebooks/controllers/ipywidgets/scriptSourceProvider/baseIPyWidgetScriptManager.ts @@ -66,7 +66,7 @@ export function extractRequireConfigFromWidgetEntry(baseUrl: Uri, widgetFolderNa // the config entry is js, and not json. // We cannot eval as thats dangerous, and we cannot use JSON.parse either as it not JSON. // Lets just extract what we need. - configStr = stripComments(configStr, { language: 'python' }); + configStr = stripComments(configStr, { language: 'javascript' }); configStr = configStr.splitLines({ trim: true, removeEmptyEntries: true }).join(''); // Now that we have just valid JS, extract contents between the third '{' and corresponding ending '}' const mappings = configStr From d9dde7181cd2e28c6c029b70168784c539b27496 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 25 Jul 2022 13:08:38 +1000 Subject: [PATCH 05/10] Misc --- build/ci/postInstall.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/ci/postInstall.js b/build/ci/postInstall.js index a4c6e5e9d87..f988dd7bd23 100644 --- a/build/ci/postInstall.js +++ b/build/ci/postInstall.js @@ -137,7 +137,7 @@ function fixJupyterLabFuture() { return; } const textToReplace = `return ok ? requestAnimationFrame : setImmediate;`; - const textToReplaceWith = `return ok ? requestAnimationFrame : (typeof setImmediate === 'function' ? setImmediate : setTimeout);`; + const textToReplaceWith = `return ok ? requestAnimationFrame : (typeof setImmediate === 'function' ? setImmediate : (fn) => setTimeout(fn, 0));`; const fileContents = fs.readFileSync(filePath, 'utf8').toString(); if (fileContents.indexOf(textToReplace) === -1 && fileContents.indexOf(textToReplaceWith) === -1) { warnings.push(`Unable to find Jupyter kernel/future/setImmediate usage to replace! in ${file}`); @@ -156,7 +156,7 @@ function fixLuminoPolling() { return; } const textToReplace = `: setImmediate;`; - const textToReplaceWith = `: typeof setImmediate === 'function' ? setImmediate : setTimeout;`; + const textToReplaceWith = `: typeof setImmediate === 'function' ? setImmediate : (fn) => setTimeout(fn, 0);`; const fileContents = fs.readFileSync(filePath, 'utf8').toString(); if (fileContents.indexOf(textToReplace) === -1 && fileContents.indexOf(textToReplaceWith) === -1) { warnings.push('Unable to find Jupyter @lumino/polling/setImmediate usage to replace!'); From 859fadab028b460f169c7618b4e476b11c05e1ed Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 26 Jul 2022 04:46:23 +1000 Subject: [PATCH 06/10] Misc --- .vscode/tasks.json | 15 ++++++++++- build/ci/postInstall.js | 56 +++-------------------------------------- build/launchWebUtils.js | 5 ++-- src/extension.web.ts | 7 ++++++ 4 files changed, 28 insertions(+), 55 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 91c203337fb..f9c81cafa98 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -68,6 +68,19 @@ "problemMatcher": [], "label": "preTestJediLSP" }, + { + "type": "npm", + "script": "launchWebExtension", + "problemMatcher": [], + "label": "Launch Web Extension (Chrome)" + }, + { + "type": "shell", + "problemMatcher": [], + "command": "npm", + "args": ["run", "launchWebExtension", "--", "--browser=webkit", "--port=3111"], + "label": "Launch Web Extension (Safari)" + }, { "type": "npm", "script": "lint", @@ -88,7 +101,7 @@ "options": { "env": { "CI_PYTHON_PATH": "", // Update with path to real python interpereter used for testing. - "EXISTING_JUPYTER_URI": "", // Update with a server that you started yourself to avoid this script doing it + "EXISTING_JUPYTER_URI": "" // Update with a server that you started yourself to avoid this script doing it } } }, diff --git a/build/ci/postInstall.js b/build/ci/postInstall.js index f988dd7bd23..673452060ae 100644 --- a/build/ci/postInstall.js +++ b/build/ci/postInstall.js @@ -126,56 +126,10 @@ function fixJupyterLabRenderers() { } } -function fixJupyterLabFuture() { - const warnings = []; - [ - 'node_modules/@jupyterlab/services/lib/kernel/future.js', - 'node_modules/@lumino/signaling/dist/index.es6.js' - ].forEach((file) => { - const filePath = path.join(__dirname, '..', '..', file); - if (!fs.existsSync(filePath)) { - return; - } - const textToReplace = `return ok ? requestAnimationFrame : setImmediate;`; - const textToReplaceWith = `return ok ? requestAnimationFrame : (typeof setImmediate === 'function' ? setImmediate : (fn) => setTimeout(fn, 0));`; - const fileContents = fs.readFileSync(filePath, 'utf8').toString(); - if (fileContents.indexOf(textToReplace) === -1 && fileContents.indexOf(textToReplaceWith) === -1) { - warnings.push(`Unable to find Jupyter kernel/future/setImmediate usage to replace! in ${file}`); - } - fs.writeFileSync(filePath, fileContents.replace(textToReplace, textToReplaceWith)); - }); - if (warnings.length === 2) { - throw new Error(warnings[0] + '\n' + warnings[1]); - } -} -function fixLuminoPolling() { - const warnings = []; - ['node_modules/@lumino/polling/dist/index.es6.js'].forEach((file) => { - const filePath = path.join(__dirname, '..', '..', file); - if (!fs.existsSync(filePath)) { - return; - } - const textToReplace = `: setImmediate;`; - const textToReplaceWith = `: typeof setImmediate === 'function' ? setImmediate : (fn) => setTimeout(fn, 0);`; - const fileContents = fs.readFileSync(filePath, 'utf8').toString(); - if (fileContents.indexOf(textToReplace) === -1 && fileContents.indexOf(textToReplaceWith) === -1) { - warnings.push('Unable to find Jupyter @lumino/polling/setImmediate usage to replace!'); - } - fs.writeFileSync(filePath, fileContents.replace(textToReplace, textToReplaceWith)); - - const textToReplace2 = `: clearImmediate;`; - const textToReplaceWith2 = `: typeof clearImmediate === 'function' ? clearImmediate : clearTimeout;`; - const fileContents2 = fs.readFileSync(filePath, 'utf8').toString(); - if (fileContents2.indexOf(textToReplace2) === -1 && fileContents2.indexOf(textToReplaceWith2) === -1) { - warnings.push('Unable to find Jupyter @lumino/polling/clearImmediate usage to replace!'); - } - fs.writeFileSync(filePath, fileContents2.replace(textToReplace2, textToReplaceWith2)); - }); - if (warnings.length === 2) { - throw new Error(warnings[0] + '\n' + warnings[1]); - } -} - +/** + * Ensures extension loads in safari (https://github.com/microsoft/vscode-jupyter/issues/10621) + * Some of the regexes are not supported in safari and not required either. + */ function fixStripComments() { const file = 'node_modules/strip-comments/lib/languages.js'; const filePath = path.join(__dirname, '..', '..', file); @@ -197,6 +151,4 @@ fixJupyterLabRenderers(); makeVariableExplorerAlwaysSorted(); createJupyterKernelWithoutSerialization(); updateJSDomTypeDefinition(); -fixJupyterLabFuture(); -fixLuminoPolling(); fixStripComments(); diff --git a/build/launchWebUtils.js b/build/launchWebUtils.js index 68270c761d5..f464eb51a99 100644 --- a/build/launchWebUtils.js +++ b/build/launchWebUtils.js @@ -16,6 +16,7 @@ const { hideBin } = require('yargs/helpers'); const argv = yargs(hideBin(process.argv)).argv; const browserType = argv.browser || argv.browserType || 'chromium'; +const port = argv.port || 3000; exports.launch = async function launch(launchTests) { let exitCode = 0; @@ -42,10 +43,10 @@ exports.launch = async function launch(launchTests) { const options = { browserType, verbose: true, + port, headless: isCI ? false : false, // Set this to false to debug failures (false on CI to support capturing screenshots when tests fail). extensionDevelopmentPath, - folderPath: path.resolve(__dirname, '..', 'src', 'test', 'datascience'), - extensionTestsPath: bundlePath + folderPath: path.resolve(__dirname, '..', 'src', 'test', 'datascience') }; if (launchTests) { options.extensionTestsPath = bundlePath; diff --git a/src/extension.web.ts b/src/extension.web.ts index d6abb1f7176..202ebb41fd1 100644 --- a/src/extension.web.ts +++ b/src/extension.web.ts @@ -11,6 +11,13 @@ if ((Reflect as any).metadata === undefined) { // Initialize the logger first. require('./platform/logging'); +// Polly fill for webworkers in safari, +// The scripts load in chrome because chrome supports offScreenCanvas which in turn supports requestAnimationFrame, +// & requestAnimationFrame is the preferred approach and setImmediate is the fallback. +// As requestAnimationFrame is supported in chrome webworkers there's no need for a fallback to setImmediate. +// https://github.com/microsoft/vscode-jupyter/issues/10621 +require('setImmediate'); + //=============================================== // We start tracking the extension's startup time at this point. The // locations at which we record various Intervals are marked below in From d0b82563e2a017366bd8ca882b3ae97b0e3670b6 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 26 Jul 2022 04:52:53 +1000 Subject: [PATCH 07/10] oops --- build/ci/postInstall.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/ci/postInstall.js b/build/ci/postInstall.js index 673452060ae..4aa3bc71d9c 100644 --- a/build/ci/postInstall.js +++ b/build/ci/postInstall.js @@ -7,8 +7,6 @@ const colors = require('colors/safe'); const fs = require('fs-extra'); const path = require('path'); const constants = require('../constants'); -const child_process = require('child_process'); -const dedent = require('dedent'); /** * In order to get raw kernels working, we reuse the default kernel that jupyterlab ships. From 98506b5ac6112792e370d4a1680bd3048e7ea46c Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 26 Jul 2022 06:51:10 +1000 Subject: [PATCH 08/10] Inclue dependency --- package-lock.json | 7 +++---- package.json | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a0ebb026a63..d16eae1edef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,6 +68,7 @@ "safe-buffer": "^5.2.1", "sanitize-filename": "^1.6.3", "semver": "^5.5.0", + "setimmediate": "^1.0.5", "slickgrid": "^2.4.17", "source-map": "^0.7.3", "stack-trace": "0.0.10", @@ -20660,8 +20661,7 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -41056,8 +41056,7 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "setprototypeof": { "version": "1.2.0", diff --git a/package.json b/package.json index 42e7dc41849..45e77af4ea1 100644 --- a/package.json +++ b/package.json @@ -2274,6 +2274,7 @@ "safe-buffer": "^5.2.1", "sanitize-filename": "^1.6.3", "semver": "^5.5.0", + "setimmediate": "^1.0.5", "slickgrid": "^2.4.17", "source-map": "^0.7.3", "stack-trace": "0.0.10", From 39bc90280e39e475c8da5f4d917d7cfb5e073453 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 26 Jul 2022 06:53:13 +1000 Subject: [PATCH 09/10] top --- src/extension.web.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extension.web.ts b/src/extension.web.ts index 202ebb41fd1..a73ad79a1b8 100644 --- a/src/extension.web.ts +++ b/src/extension.web.ts @@ -8,9 +8,6 @@ if ((Reflect as any).metadata === undefined) { require('reflect-metadata'); } -// Initialize the logger first. -require('./platform/logging'); - // Polly fill for webworkers in safari, // The scripts load in chrome because chrome supports offScreenCanvas which in turn supports requestAnimationFrame, // & requestAnimationFrame is the preferred approach and setImmediate is the fallback. @@ -18,6 +15,9 @@ require('./platform/logging'); // https://github.com/microsoft/vscode-jupyter/issues/10621 require('setImmediate'); +// Initialize the logger first. +require('./platform/logging'); + //=============================================== // We start tracking the extension's startup time at this point. The // locations at which we record various Intervals are marked below in From aca4f3f829ea56f66162d56c4821257da5db343a Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 26 Jul 2022 07:36:05 +1000 Subject: [PATCH 10/10] oops --- src/extension.web.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension.web.ts b/src/extension.web.ts index a73ad79a1b8..f207cf8333c 100644 --- a/src/extension.web.ts +++ b/src/extension.web.ts @@ -13,7 +13,7 @@ if ((Reflect as any).metadata === undefined) { // & requestAnimationFrame is the preferred approach and setImmediate is the fallback. // As requestAnimationFrame is supported in chrome webworkers there's no need for a fallback to setImmediate. // https://github.com/microsoft/vscode-jupyter/issues/10621 -require('setImmediate'); +require('setimmediate'); // Initialize the logger first. require('./platform/logging');