Squashed 'lib/vscode/' changes from fd6f3bce670..ead2c2ab0f5

ead2c2ab0f5 Merge pull request #120858 from microsoft/alex/1-55-2
bfb2654224e Pick up new distro version and bump version
08a217c4d27 Merge pull request #120733 from microsoft/joao/release/1.55/fix-build
6b89f1aaa2e Don't call node-gyp anymore (#120673)
6e3220a31a9 Merge shellEnv into process.env (#120332)
5dee7d559ff Update to vscode-proxy-agent 0.8.2 (#120354)
91fa7f030d2 Merge pull request #120519 from microsoft/misolori/icon-updates
c5e030273bf Merge branch 'release/1.55' into misolori/icon-updates
8be12407ad0 bump version to 1.55.1 (#120379)
d6e72b493ce debug: update js-debug (#120358)
b7d152d5b2f Update distro
c185983a683 Fix table list height. Fixes #120062 (#120102) (#120168)
c71be15869a fix powershell profile source (#120138)
4c2a1fa6306 handle error when wsl is not installed (#120128)
e3297826776 Merge pull request #120107 from microsoft/aeschli/120103
c7f963cb27d Moves extension prop out of proposed
55f4c2ec1e2 update typescript-vscode-sh-plugin
26a60dbecac Merge pull request #120081 from microsoft/sandy081/fix119975
5753889f2d1 remove overflow action when there are no overflows
be363080a36 fixes #120066 (#120080)
554774c21d6 Merge pull request #119983 from microsoft/lramos15/notebookViewType
428daa3650c Merge pull request #119990 from microsoft/tyriar/r155_wsl_compile
64876cb88e2 Fix test compilation
00296950306 [Getting Started] new file => new untitled file rather than explorer's new file (#119981)
2a8113f7231 Enable terminal event batching from ptyHost (#117268)
aefdd723bd0 Merge pull request #119987 from microsoft/tyriar/r155_wsl_setting
98aeda8479a Remove RemoteHub from desktop stable (#119972)
981a2b53abc Merge pull request #119977 from microsoft/digitarald/fix-115327
a3514cd1481 allow terminal profiles w a source to have args (#119967)
78636f2c133 Fixes #115327 with HC images for GS setup/beginners.
b72964aaace iPad OS ctrl + c in terminal  (#119979)
a84f17acbbf displayDetectedWslProfiles -> useWslProfiles
1b0b1c67f35 Merge pull request #119973 from microsoft/digitarald-ces-distro-update
c97d55a2131 debug: fix stop on entry not working after launch.json change (#119980)
c7068ae9331 Respect viewtype for reopen with in notebooks
59b2869bdb1 Distro update
7208128b818 Merge pull request #119377 from microsoft/digitarald/ces
522cb113395 Ignore extension that is being installed
d06d2f1d624 Update distro
80c9c2bfdd8 Adopt writeSync maxSubsequentCalls
dd8ce595220 xterm@4.12.0-beta.7
1eb987f85f1 LocalizationService.update no longer needed. Fixes https://github.com/microsoft/vssaas-planning/issues/3290
70aab480c5a update labels for break commands
49ad7ad4f53 fix optional service typing
a0aea2c02ab Fix counting executing cells incorrectly Fix #119921
961935482ff Fix build
33c5dbf0407 Force internal execution metadata to be transient Fix #119853
0865813de51 showQuickLaunchWslProfiles -> displayDetectedWslProfiles
91b6bcd2cce Fix spelling error
5bf977258c5 Slide to first category for new users
72bb797593f Don't scroll to first category if already have Fix #119842 Fix #119339
0a7dde45706 Update distro
9be5cb7f482 Fixes #118772: Remove a disconnected remote extension host from `extensionHostManagers`
c9829c32d11 Surface pwsh as a profile on mac/linux if it's installed
b59b0c5051e update distro
647f8724320 Roll back to `vscode-textmate@5.2.0`
a564f58b13f Fixes #119065: Also listen for EPIPE errors on the socket
99c8eb69942 Fixes regex - codespaces remotes are missing .git
ab39731a1e6 Avoid rolling back `vscode-textmate`
9b564ad40db update distro
85d03e9c382 Fixes #119915: Go back to `vscode-oniguruma@1.3.1`
f4f1bdb9265 update distro
e15a185f6ee Merge branch 'main' into notebook/dev
a6cef60b50f notebook toolbar init display be none. fix #119910.
654b5e80469 update to latest `vscode-oniguruma`
5a92084faeb Use ThrottledDelayer per review feedback.
357c13ac467 localize info message
5dcccb92e38 fix #119854
1ca4e703ba8 Optimizing newly add getting started images.
71d2102d7d0 fix #119803
c5d901812cd Merge pull request #119883 from microsoft/tyriar/webgl_fix
f7cc0f2c79d Adding light and hc getting started images. Closes #115325 and #115327
64256f22d66 Merge pull request #119895 from gregvanl/settingTypos
ad659fb25aa Allow null in profiles config
3e6f65a3acd Merge branch 'main' of https://github.com/microsoft/vscode into main
a30b6bfdc3b remove default value for overrideName
19bbe2edbee Remove extra space from error message
7ac7d4438a9 fix #119672
975115a2cb4 Setting descriptions typos and formatting
fe6b3e258b6 Re-enable measuring
c5a8eed0334 Accept array or single item for output items methods #119601
996391b87d3 Move proposed api piece into stable typings
6ebe2a14f37 fix #119852.
3d1d01690df Fix canvas -> dom fallback
da992a171e2 fix scroll cells from bottom view.
9ab0fb227ee use app scope
81a08478ef1 updated notebooks
ff869cd3581 Merge pull request #119878 from microsoft/isidorn/notificationVisible
1a184f9e9dc add visible flag to notification
b70c4fee0d8 Fix default webgl renderer
ad026f8130c ces: use ThrottledDelayer
755cbf5412a Merge branch 'main' into notebook/dev
08c4cd87e3c Reenable localization tests.
5064fae294b Fix #118134
e8111f76b5b Fix #119855
5b636c4a7b2 Revert "Fixes #111814 (#119475)"
6f726bcdf6a fix #118442
557c4b56995 update verification members
63f1721ed85 don't store output in GH issue notebooks
05ce54df77c testing: remove unused contributions
ce9298464e4 bring notebook actions back to editor title bar menu static.
ceff50539f0 re #119706.
ef80780f632 fix #118996.
383fb64cc58 remove displayOrder and fix #119830
81ba1dae860 Fix #117540
1a425eacb83 Accept single outputs or arrays in execution task output edit methods Fix #119601
75ed057885c fix #117937
1e6697ed77d fix #119561.
f0eacf87700 fix #119767.
1d3cbad0102 Wait for extension registration when resolving notebook viewType Fix #119686
ab317a2280e Hide select terminal profile in yarn web
a0e8b01ec49 testing: polish wording of testing.autoRun.mode
189fb15df90 Check PATH when validating non-absolute paths
5c6836eb44d Fix #119699
b63cfb3a8b6 skip test and remove unused code
8d6c2a23888 Make drop shadow much more subtle Closes #119633
23713de2bee don't emit events when splices are empty, fixes https://github.com/microsoft/vscode/issues/119608
5a241c767a9 fix https://github.com/microsoft/vscode/issues/119363
22212f5de84 use APIs over commands, fixes (?) https://github.com/microsoft/vscode/issues/119437
bd2402a6e8e Add double-click to collapse Fix #113248
c45540033a5 Aadd messge when getting started empty closes #119496
d115bb2a977 clean up statProvider, use existsFile, fix #119807
008e91bd7c9 contribute editor toolbar actions by checking active editor other than focus/blur. fix #119706
38160c823c8 Fixes codespaces fork on push
d765f3a43c7 testing: fix list view not working
0fb1882984e fix: items from results being added to collections and breaking decorations
ab94ad2b8f5 clean-up validateProfilePaths
46d5d38dd28 fix #119672
ebec68bc3d9 fix #119728.
2616ee94f38 fix #119775.
6384c7462f8 fix #119677
abaa23cdf39 fix #119774
09f43fd6aa4 testing: fix exclusion filter in view
e4bb4c1b77f testing: fix results disappearing or not showing for new files
cd31f2cdfac testing: fix test appearing on first line, remove location from TestItems
60849897630 fix #119773.
15ba6b4c957 Revert "extract _assertWebviewForMarkdownPreview"
2c232fed6af Update README.md
e3e7fb0b2ab Set explicit mode for markdown preview code
addf2d6d9e9 Fix spelling for gitignore
f8c1ffbb0cf Build simple-browser media during watch
68e582380d7 Maybe fix bug where sync task doesn't get checked
d087b5cf4f1 Add back old getting started flow as "walkthroughs"
e5afd670959 extract _assertWebviewForMarkdownPreview
d13e68e6cf5 avoid markdown preview removal when it is disabled.
8a960081e55 fix #119771.
f1334e055c8 Polish select default profile quick pick
563a617ca2a Applied review feedback and tweaked heuristics
8aac8643d77 Use 'terminal profile' instead of quick launch profile, change icon
64b4f5b934d use final DAP 1.46.0
f04acbd22a4 node-debug@1.44.19
0db170025e4 Fix terminal dropdown rebuilding itself
8ceb8b96153 Rename "expand cell content" to "input" Fix #119762
9e2e6cded21 Change cell pending indicator to clock codicon Fix #119739
ddb7709cbf3 Fix #119700 fix #119731 fix #119701 Co-authored-by: Daniel Imms <daimms@microsoft.com>
51c403193b6 do no change selections if the action is from toolbar.
7d19db7ad9b fix #119769.
f934e058c75 Fix profile permissions prompt on linux/mac
6dbb3800c5a Fix #116424
b8f5fd7f1b6 debug: update js-debug
c88146514ca debug: bump node-debug
8387a46298e snap-build-linux.yml: use "snap pack" to get LZO (#119478)
792c2318898 fixes #118660
eb135ec46e8 Fix #119626
e353502fb9d fixes #118045
f9d92f0fc6c Fix #119723
948839aa445 Fix #119660
6aa6260a843 fixes #118852
da1ed96b6a8 fix code-cli.bat
aeedd850ac4 fix #119073
2d9069014eb Add a placeholder for already forwarded root ports (#119792)
74cf3fb2021 Fixes #119529: Wait for eager extensions to activate before launching extension tests
5fbba30c046 Better Fix #119573
9a646e1967c fixes #119487
f91c464f1e1 Merge pull request #119784 from microsoft/tyriar/profile_schema
9f37f3f04ee Pull common unix/win parts into shared function
ac74acadddf Only set when win profile is non-null
f4fbc4abd78 Merge remote-tracking branch 'origin/main' into tyriar/profile_schema
a83eb44ecd5 fixes #119488
301e9ac1db8 fixes #119580
a34297a6085 fix #119384
47f0413ea29 window indicator: based on workspace config file location. For #119752
40d104ad84a Add schema to profiles settings
771b0192f43 window listeners handling
27fc3b41ed4 scm: add trace logs for #113803
08d5310eb18 update verifications notebook
8933c1564d0 Don't create a terminal on panel show without proc support
c55aff63798 API feedback (WorkspaceTrustRequest -> WorkspaceTrustRequestOptions) (#119658)
3eb6fec8cd6 Be more specific when listening for marker events
4ad88afc1f2 Fix #119573
42b8129c64e don't emit events when splices are empty, fixes https://github.com/microsoft/vscode/issues/119608
4dedb019f85 Clear data written flag on manual relaunch
1c3990938b8 Fix #119572
443b6f71bf8 fix https://github.com/microsoft/vscode/issues/119363
c6a8cb7f091 Fix #119698
8437d38d364 Fix #119753
a1ecc83a5d3 Merge branch 'main' into notebook/dev
a233c8683a2 workspaces history - proper check for untitled
7a1302a2b6c remote indicator - fix npe
90484dda2b2 shared process - also log if window visible
5245290dc56 file working copy - update test to account for events
2b66dfe0218 skip flaky tests.
d5abce78ab7 Remove unsued var
ff42bf46511 Disable markdown renders by default
279b4d92317 fix #119724.
514eefb789e Don't send execute request for markdown cells Fix #119734
91939fb9e7d handle invalid ignore options and avoid early dispose. fix #119638
548de3ac8ba fix #119708
85770c31911 hide all outputs (builtin and renderers) fix #119690.
a8b8e7bd483 Fixes #118979: Reduce find widget's z-index
11c0904a568 Don't enable the new markdown renderer if accessibility mode is enabled
376b25645be Only show selection if there multiple cells selected
31987b11c6f Merge pull request #117758 from conwnet/main
02b394a1a5c Add a special editor option to control the readonly textarea attribute
a9aebe3bce0 Merge remote-tracking branch 'origin/main' into pr/conwnet/117758
07eb4d9e076 Fix #114965
d7e1da38b17 Fix Linux referring to osx
8d3d8e0cd04 html: add vscode-languageserver-textdocument as dependency
bd18fe9bcec Fixes #119632: Handle `undefined` when validating a range
8c7a3d8f6ca html: fix compile errors
c099b873de7 update distro
0f65e64c2a3 Fixes #119636 - 🤦
76c5d1707cb RunOneScheduler and code cleanup for CES
b3058d60df4 update distro
7b7e3d9e1e5 Fixes #118041: Add workaround for `UTF16` `TextDecoder` eating up `0xFEFF` and `0xFFFE`
c7ad1b9020d Add sequences to type ahead comment
97b2514ca71 include source.id for progress notifications
6349f37d80f Merge pull request #119373 from wdesgardin/fix/replace-pattern-preserve-case
cca8a48b17a Restore notebook smoketests,  Fix #113882
3225cf3037a update distro
3b44bb422d3 Only set detected profile if value is non-null
75f796dfb48 notificationTelemetry: id should always be a string
4eb625f0cf0 [html] update service
a53ce8af3b5 update remote indicator on workspace change
11e79c76d89 Merge pull request #119607 from NotWearingPants/patch-3
a780b76b9d5 Keep text from jumping when showing port input Fixes microsoft/vscode-remote-release#4729
61eb66d6c4b Fixed recent typo from afca445
64381abea97 unconfiguredPortsAttributes -> otherPortsAttributes Fixes microsoft/vscode-remote-release#4732
73b9e6679d5 Update README.md
a535549d893 update distro
f600cd9ef21 Fix compilation errors: update to latest `vscode-textmate`
684a4526059 Improve resolveTask documentation
ab12e39334e update distro
788c9dfdc48 update deps
afca44535df Add a trace statement to be able to track down which implementation handles a `MultiCommand`
9089e0cbd9f Update endgame notebooks
b28d8ca9fe0 use APIs over commands, fixes (?) https://github.com/microsoft/vscode/issues/119437
2bc5e538923 Merge branch 'main' into notebook/dev
ebe56205433 fix(search): preserve case when match start with lowercase char
a6f6b4aa8e3 Add feature flags to control availablity of getting started extension contributions
735e998fca0 update distro
10a74ff5c51 Open to getting started page on extension install
194c37b4cf2 Fix test for latestExecutionSummary init
9fa49ba9415 ignore optional dependencies when webpacking
7a8b665f25a Fix missing prop on cell data
808266d4dec Allow tests to be loaded asynchronously (#119537)
6e2cb85e207 debug: update js-debug
fdc4f23b108 Add double-click to collapse Fix #113248
35ae55affde diff editor output decorations fix.
aac461a3124 Improves behavior for #114945
851a849d2ce Don't validate non-absolute paths
2cde743fe21 Pass event modifier data when clicking on markdown cell
4cb75127664 add quick launch profiles for unix
9c00242866c updating telemetry module for built-in exts
3d987fdc5b3 fixes #117782
084fd5171a1 Terminal profile fixes (#119352)
7483058a0ab update distro
1f5dd686c8f Disable select for notebook preview cells in webviews
a685b5976ba Exclude DSR from type ahead
4b3ba3ea44c Removes proposed api check
44ffe526ffe auto layout for editors in output container, fix #119048.
d4a0fa9ca6d Build getting started service at startup in order to init event listeners
d657779c014 Improve getting started response to slow network conditions for content overrides
efb75d7262e Move override delay to conver all exp service usage
018eca5246f fix #118615 'scm/resourceXXX/context' extension point descriptions were muddled
0179466adac Move getting started service to workbench/contrib Closes #118603
e8290f52f4f run oss tool for 1.55
db670f1002c Use shellEnv (#108804)
64042213ed2 Bumps RemoteHub to 0.1.2
f201f7bc68a Fix notebook test
08cf8038dfd Merge pull request #95882 from jeanp413/fix-95671
4977db85c01 update tas-client-umd
7e719d3f046 Merge branch 'notebook/dev' into main
03e1ce6524d Fix getting started items appearing out of order
4a83a80aa7b update diff output height properly (using closure) on resize.
2949009de61 move more logic into abstractRenderer.
55e56ef9153 add options for controlling outputs/metadata in the diff editor.
0089ba3ae1d Bump vscode-emmet-helper, fixes #112675
c95389a7b2d Fix emmet completions in scss (#118666)
7b96cc4c8ba Implement Execution API (#116416)
4b0118871f0 Adds codespaces lookup via command for desktop
d46eca3d2dd Merge pull request #119385 from microsoft/merogge/fix
7176a40fc74 Add notebook.inactiveSelectedCellBorder (refs #114156)
64a8be3fa24 fix #117691
a2044cbd78d tweak
d909932d240 Fix #118104
33c11ec866f Bumps RemoteHub to 0.1.1
26cdfad1cd0 Fixes #118521
e79b88daadb handle view in terminalView
66961037cc3 Fixes #111814 (#119475)
57aada6cca9 Fix test
5efebbd4c4c Fixes #118270: Add new option to control deleting character pairs and delete by default only auto-inserted closing characters
91e41167e52 file working copy - clarify onDidChangeContent
8cfc30d5741 Fixes #118461: Don't show Open Workspace in the diff editor
c148f9a70bf Show error when port is already forwarded Fixes #117571
d239450d9b1 Ensure relaunched processes get shutdown
76b1ad1d1dc Improve profile order, remove profileName from config
6bac57decf7 file working copy - better document resolve() method
0ddc091edc6 some code 💄
a02448d6852 Ensure config service is optional in external terminal
917edde164f Fixes #117534: Allow to mark command args as optional
2cd8246a94b Fixes #118062
4c29fa41c6d Fixes #119416: Use control pictures for NULL and DEL when renderControlCharacters is on
cc8748a2397 notificationsTelemetry: change id to be string
bbe333f8782 Add tsec exemptions
42c9e63a7ed file working copy - resolve returns void
d9d0879741f file working copy - add save as support and a lot of tests
469e4f6e275 chore: bump distro
67eebf8ac58 avoid duplication.
0ab3c62ca2a fix action context detection.
5a0fe1f6a89 remove todo tag
d6a0bf700cd Merge branch 'main' into notebook/dev
5a66c91c029 Fixes #117935
a3415e669a8 Fixes #119383: Use `fetch` instead of `importScripts` to avoid deadlock in Safari
4a10c93b2d6 Remove unused argument
307ed64376a Adds RemoteHub as built-in
8290994dbbe Fix localization strings and typo
4995ce93673 More tweaks to geting started category
13ec92fe360 Update getting started category styling
e380c34cac7 Fix typos
a1c114aa9e6 replace more pathOrPaths with path
1aa0c31b55b pathOrPaths -> path
e7aedd975c8 Adjust notebook cell multi-select colors
4bcf96223a7 Fix some getting started crashes
0d83680d528 More CES heuristics work
d222e20941c Merge pull request #119328 from microsoft/tyriar/wsl_encoding
e92a80bb641 Merge remote-tracking branch 'origin/main' into tyriar/wsl_encoding
ee4b50aaa43 Allow creation of quick launch profiles via select default shell command
194f43025f6 Remove log
da7c7d1efea Merge branch 'main' into digitarald/ces
4b5354c5f98 alternative version for notebook document.
ff3c423cf3f alternative version for notebook document.
6480a6f20ea feat: add option to control scm font size (#115494)
d60cac30195 Fix a typo
f8acb0d6f63 Adding the 'delete branch...' function to the source control > branch section
6c0c77926ff Improve GitHub repository search
64ebc978e76 Revert "Use rmdirSync instead of rimraf"
0eff78fc42e Merge branch 'notebook/dev' into main
7f9ea9411c8 Reduce default tas override delay to 0
5c0c637a043 Make sure we ignore compiled media files
f5146529508 Automatically relaunch terminals when pty host is restarted
7727e93b22e Rename experiment override settings Log when experiments have been overridden for purposes of excluding data from scorecards
07879df53d9 update the layout since editor toolbar height changes
13ceef289f0 experiment service for nb toolbar position
1cd067471e8 Trims url to avoid issues
022d823577a Fixes #110904 - adjusts error regex
c2b6d30e9ef Fix input placeholders from 2275dba01afe2b8814d4ebdd67d1027fa51bdcb4
b1770e6ad8a Prompt within 1-8hrs heuristics
df3953996da notifications: send telemetry for silent notificatinos, smarter spot for hide event
f7f2f08eec5 Update distro
1b7470b25db Try to find ports with a root process (#119341)
421d67ec41a notifications: add source to notification:hide and also send events for silent notificatinos
2275dba01af Change files to include/exclude placeholder to tooltip
3d87801cb0c Merge pull request #119091 from microsoft/joh/nbSerialize
9734ab15dd6 💄
88e87f02bd6 file working copy - make resolve not return "this"
b74bae8ced6 refine NotebookCellData converter
d6c74de1f5c Merge branch 'main' into notebook/dev
61b73024053 Merge branch 'main' into joh/nbSerialize
3a6c54fb14e no more file watching in notebook diff editor, remove lastResolvedFileStat from notebook editor model
39ea9cac052 Make UI progress indicator clearly visible in the quickpick (#119293)
8cf7c12fd33 fixes #119331
d10866cca54 Fire onExit for feature terminals that lost pty host connection
7fa2b715ef0 Merge branch 'main' into joh/nbSerialize
b33801c2c66 file working copy - first cut tests
8736be196db Properly join string[] profile args
f68f1845d23 Move comment to the right place
2b2ff3e5e08 exec with the right encoding
ede3632a560 pimp up workbench-web.html
85cf30ab517 Properly decode wsl.exe -l output
163aeeedac7 Prevent seamless relaunch triggering multiple times
c64a8d59270 file working copy - use IDisposable not Disposable
bae75adfb41 no more double dispose needed in _onWillDisposeDocument
af10c8f65b5 Fixes #119051: Prefer fewer diff hunks
3271248da68 Merge branch 'main' into joh/nbSerialize
7902c6edcd1 remove NotebookService#destory
c8dc60adac6 Use widget.shadow for custom hover contrast
a07a508be8b Update distro
a02fabb6d64 file working copy - dispose model when working copy disposes
dfe12887da0 xterm@4.12.0-beta.3
06901e67a38 remove todo
3fd2415c9f7 Show args in profile selector
46d1ea3a2c8 fire event only when save succeeded
8410aa8f2e6 adopt name change
fee37f32af6 Merge branch 'main' into joh/nbSerialize
3f71de52eef Also exclude docker-desktop terminal profile
7d99c47b755 move notebook save event into notebook editor model service, remove resolve/save/backup from notebook service and let editor model use content provider directly
06e8814b29b Merge branch 'main' into fix-95671
5dad121bcb1 Merge pull request #119315 from gjsjohnmurray/fix-119261
a255250be89 Add a user setting for "workbench.hover.delay" Fixes #117894
156fed280ac fix #119261 filter also by description in Insert Snippet
1dbcde0f1fc Fixes #119065: Handle errors also using the socket.write() callback
958171a700d Fix port process finding starting even when using output
56b55c26070 #38607 Handle uninstalling extensions
a27b6f74497 implement load of the notebook model
f841a70b0c0 file working copy - rename `forceReadFromDisk` => `forceReadFromFile`
c8975ceaecd file working copy - remove getStat() that is only used in tests
8595f6f5d03 Update to align log level constants
23fa2860d3e add withNotebookDataProvider as strict variant of getXYZ, sends activation event, throws when no provider found
c17a5ca80f7 Merge pull request #100027 from matthew-haines/master
bed126ce9d7 #38607 Separete installing & installed state
6608083a3d4 💄 window error telemetry
ce3ebc9f5a6 add test
391b1a6b576 Add support for `"log": "<level>"` to the argv.json (fixes #118824)
d96f34c867b Fix #38607
e800c205df8 Merge branch 'main' into pr/matthew-haines/100027
b4fb4d8c2ff recognize .axaml as xml language Fixes #117298
abd1e0166e9 Merge pull request #119250 from noahbliss/patch-1
414a7eb7e06 Fixes #113614: Catch potential errors thrown when searching in the extension gallery
9710ecf1c66 Merge branch 'main' into notebook/dev
af8d8116eec Merge branch 'main' into joh/nbSerialize
9b5eceb1f66 💄
4f1cdb7aa0d flaky suite for #118969
d0f2d7eee63 build
e4b1e9ac57a Give room for border
0932039e138 Allow for exp modifications of getting started content
22c40603121 Extensions => Command Palette
5e0602716fe Small tweaks to styling.
fb8811e513b Add "copy cell down" to toolbar
7a9844238d8 terminal profile fixes (#119267)
c0885dd0c4d Add task to build extension media (#119294)
b0f4dba5d29 handle blur from other browser events.
3eae316f513 more padding for global toolbar.
99dd29307d1 no layout if not visible.
6d654b9bc9e polish css.
a99306b4871 Update padding for notebook toolbar & folding icon
fbcd54712ef fix duplicated actions on reload.
41ecc1eda5a cell output domNode npe.
c37f743a99e schedule task should check disposable again.
b814edf4735 keybindings for actions.
ece0761b33f swap notebook toolbar and editor toolbar.
1b52d828711 Revert "fix profile tests, path -> pathOrPaths, and  exception"
a5219a9350c path -> pathOrPaths in terminalConfig
e9e112a6483 fix profile tests, path -> pathOrPaths, and  exception
859edd7f4f0 Merge pull request #119292 from microsoft/misolori/get-started-polish
89135921788 Increase bottom padding for card
45ef6493842 Adds support for fork on push for Codespaces
f8b50611060 Polish getting started items
3b3b9be7062 Fixes #113811
746c323a55a Merge pull request #118830 from microsoft:aeschli/testsinwebworker
242ddc4bdf0 Merge pull request #118400 from thebinarysearchtree/main
c576cad0912 #38607 make renaming extension aware of other sources
89d8eed14f0 Allow extension authors to set the title of a QuickPick/InputBox in Options (#119144)
31a9b8f8158 Fixes #62307
14c4257e75d Fix background for markdown cells
651f0ee28a1 Simplify removal of (Default) from distro name
aef8a2af5c6 Improve encoding workaround for wsl.exe
9d2478b6259 Don't name quick launched terminals
a7bafc2a9a5 Add logging around port notification Part of #117790
342a55d10d7 worker eh: wrap console and send to renderer
7c4b2b09de1 add workbench-web
2ace42b0cc1 Don't attempt to create term in yarn web
9cd4712b352 file working copy - update todos
6bea69b5e2d Fix break
3a39aa41f5b Fix hiding tree hovers Fixes #118755
65fb4037a39 adopt latest working copy changes
59ee7787595 Merge branch 'main' into joh/nbSerialize
232266aaf22 first cut of IFileWorkingCopy adoption, misses saveAs and backsnapshot are improper...
2d7b64d423d add notification:hide event
9c204017ffc file working copy - remove _backupSnapshot
be93116b735 Replace "Favours" with "Favors"
9f773417714 Replace "Favours" with "Favors"
a23d2d40f31 Merge pull request #117994 from GitMensch/patch-1
4c9d23c8f57 file working copy 💄
adf6e065194 Fix ugly selection border on Add Port button Fixes microsoft/vscode-remote-release#4689
0b758c4e0d6 Unix profile selector (#119213)
abbd77d0188 Merge pull request #119075 from microsoft/isidorn/notificationsTelemetry
99d2cb82e59 pick up notification source ID properly
5804f7dd83a Merge branch 'main' into aeschli/testsinwebworker
8af8a869dc8 Merge branch 'main' into joh/nbSerialize
3da9f36645d Cancel packagejson search in npm after 1 second
c359effab04 Fix unconfiguredPortsAttributes in devcontainer.json
abb6ff6d93e file working copy - dispose working copy when model disposes
733f9323a46 Initial file working copies (#119233)
970d1916421 file working copy - self register to working copy service
1902dcddd8a file working copy - add onDispose
6d02fe2cb75 fix #118945 validationMessage on extension InputBox lacked Severity.Error
943ab428d72 file working copy - more cleanup and alignments
d2afd69d310 file working copy - some cleanup in working copy
111a6cec70f Don't include build files in repo
3e4c057624b Make sure we exclude ts files from published build
043a0ee0d94 Try cache busting on reload in simple browser
b9f33fc242d Rename CodeActionKind.Manual -> Invoke
52201359920 Scroll the notebook while dragging a markdown cell
e7f3b77a9c8 Remove typings for unused package
a7ae58f4dbb Use rmdirSync instead of rimraf
05e970086cd Add missing change session events to ms auth provider
b0bbf9c19ee improve pwsh logic
e01b60782ae Exclude compiled notebook files from hygine
42af2c38dd2 Merge pull request #117835 from yannickowow/master
7ccf0b03c60 debug: stepOver should be alt+F11 on windows browsers
8a095f4d233 Update test associated to DataBreakpoints
cf7e6f31f9c Support for DataBreakpointAccessType condition #117835
82cf09af92e file working copy - first cut manager
c332b6bea79 tweak grammar
31f3f2e6195 Add placeholder text to include/exclude boxes Fix #119107
547312993f8 provide extensions sync state version api in web - reset the resource sync state when the version changes
6f0d3d5c9f5 debug: do not de-dupe same named variables
fbc577e6f04 Double click to set port label Fixes #117573 Fixes microsoft/vscode-remote-release#4624
5b21b951ecf Fix Add Port row click Fixes microsoft/vscode-remote-release#4687
fc1d49f95ed file working copy - make sure to bubble up errors
03e3fce973e file working copy - first cut extraction from text file model world
b335d9eaf10 Make "Set Port Label" an inline action only Part of microsoft/vscode-remote-release#4624
fdb91e27d3d Add new unconfiguredPortsAttributes to config edit
a268122729d Add more docs to PortAttributesProvider Part of #115616
1c6fcca5710 Fix #115039
c9fd3403447 fix https://github.com/microsoft/vscode/issues/119157
b12279b40c5 Get correct candidate for checking port attributes providers
fd57115d52c Allow for manually/programmatically checking/unchecking tasks
b353f063393 comment out failing notebook smoke tests, https://github.com/microsoft/vscode/issues/119164
06ee68d4bbf api notebook update
5bb215e893b Increase spacing between tasks
26a77fb7fb8 Clean up formatting
08877abd68a Relocate keybinding rendering closes #119113
970bcad11a4 Fix bug where expanded tasks did not adjust height on layout
1bcf2a3f1dd Tweak getting started to look more like welcome
9e470ce1efc chore: update distro
0585c2e05a6 Remove experiment (#110330)
ff1ce589e73 fix #119130
fc8d7681c4a Make sure katex styles are shipped under root of
581a659d427 Update markdown notebook scripts
806c22dcc91 Skip multiple tabs test for now
a7006f93215 Fix potential null access
f6f51117008 Update walkthrough contribution api to single object model Ref #119097
e8e6d64105b  Terminal profiles  (#118790)
e5fc49d8af8 Fix markdown editing code cells not having top margin
c09b3d2358f typescript: enable built-in 2020 semantic token support
1b695635457 Enable markdown renderer by default on desktop
83d80e8bcaf Don't try to relayout markdown cells if their height has not been set yet
772effc6e6c bind mimetype switcher later.
9063d4ac766 finalize InlineValuesProvider API; fixes #105690
9205c8bd920 Improve terminal key dispatch message
5615bb9eee4 Merge pull request #118725 from microsoft/joh/117273
a6b7fccdaab support appending per mimetype.
7af7449a295 add extension id to source of notification
a294694b583 Fix padding in webview based markdown cells
a7bbb5502dd notifications.test add tests for service add and remove events
99597e3974a delete cell handles multi select.
b3e7d37b8df clipboard actions handle selections around the target.
562962afc9e move copy,cut,paste into clipboard contrib.
30845ba2037 Include community in README.md (#119105)
19ac5d4a5c5 Merge pull request #119114 from microsoft/tyriar/118804
9ed0aa6c914 Fix type ahead issue in relaunched terminals
7243e13db16 Fix #118818
8303d03545a aria alert for cell index changes.
5f4e9a55f5a join with next cells through multi selections
4f488a7cf21 support both selections and ui actions.
4d3df5cd983 join cells with multi cells (single selection)
881e370539e add tests for joining single cell.
3f7651fed04 move join/split cells out of coreActions.
184560bb0ce tests for moving and duplicating cells.
4855eb46a0a make notebook unit test easier.
3ee43778c50 Merge pull request #119092 from microsoft/tyriar/118066
29abc8f3499 Merge pull request #119024 from microsoft/tyriar/116022
3e05837735a Merge pull request #119084 from microsoft/tyriar/118256_test
143f4e6fa2b Merge remote-tracking branch 'origin/main' into tyriar/118066
7a6944d2d0d Add unit tests for TerminalRecorder
5141aba1941 polish
7c0e20ca4c0 Allow terminal recorder to avoid initial resize event
b6921c2f2d6 api notebook snapshot
9a7366de9bd Prevent process ready log firing multiple times
32406c3f6ab Recalculate trust when workspace folders change
b1359b271c5 Fix focus + keybinding issue causing input box in Ports Fixes #microsoft/vscode-remote-release#4678
0cd2ba8bddb Merge remote-tracking branch 'origin/main' into tyriar/118066
df97bc32ada Tactical fix for watching problem matcher and closed documents Fixes #116760
508b6cc7864 💄
f56b5cf7cef react to feedback
b38200cf0a3 Ignore testWorkspace tasks.json
2d536914ea1 Await task config updates
f0ee79acfd1 Update src/vs/editor/standalone/browser/simpleServices.ts
846917d51fd Update src/vs/platform/notification/test/common/testNotificationService.ts
77e2397c121 Update src/vs/platform/notification/test/common/testNotificationService.ts
3765294bb11 Update src/vs/editor/standalone/browser/simpleServices.ts
5da95f0e11d Merge remote-tracking branch 'origin/main' into tyriar/116022
31283f32b2c keep notebook serializer locally
d1e5c8cddf4 Fix portsAttributes.unconfigured setting name And fix setting update not read Fixes #118991
e8f5186722f Improve task test layout
76cd8a00b37 Fixes #119011: Wait for the vscode API to become available before launching extension tests
1b9a61662a3 Regression test for #118256
b8476ece198 Fix task start firing with invalid process ID in dependsOn task
6fd693ec9e9 more deprecations
f2761b584a4 ignore file events while saving, more logging, https://github.com/microsoft/vscode/issues/118992
9426cea171e Ports: service -> application, defaults ->unconfigured
b33ce0ff5d9 Update types
2de06d768bf add INotebookSerializer interfaces and wire up IPC calls
3014c755cd7 Pick up fix for #117054
21d20148ee5 new debug setting for clearing a terminal before reusing; fixes #116699
70abcfc7689 add notification:actionExecuted telemetry event
66045febfe4 add notificationsTelemetry
45ea71d8c37 notificationsService: onDidAddNotification, onDidRemoveNotification
149a8b71c53 Workspace trust changes (#119017)
e787d6e3843 custom editors - make conflict resolution actions appear (#118949)
5060cbe7bc0 Merge pull request #119012 from Daniel-Knights/patch-1
537c648fb57 mark APIs as deprecated
b5eff84359d fix build
b89cf5c0aff Adds RemoteHub to api allow list
4222a0981e2 debt - use product quality instead of probing for name
a7f5a101589 debt - some more process and platform 💄
892a1083cb2 Fix border overlap in quick pick UI (#119039)
405d2cfbda4 Merge remote-tracking branch 'origin/main' into tyriar/116022
70a47bb275d Enable vscode.Pseudoterminals in web worker ext host
813bb397b01 update list item height on markdown cell ctor as we might already warm up the viewport.
fbf1e77578d adopt multi select in drag and drop. drag the focus or selection around the focus.
84f16040107 share drag impl for builtin and custom md renderer.
12adb0178f6 test view/model range convertion with hidden cells.
51a15dee0a2 update seti theme. fixes #118912
7f43e5c846c unHidePreview should also update dimensions
d949fd3bc09 Don't create markdown previews if cell is in edit mode
2f8d4892884 fix: typo
d7c0ea59d23 Rename setting gettingStarted.hiddenCategories => workbench.welcomePage.hiddenCategories Fixes #118990
8e2fc51526a Remove only
f390023d7e6 Remove unused
385cb56165e Fix #118953
5e09ecb9ab2 Fix #118958
83b6cdc6107 better aria label for the remote host status bar item
ad428ea8910 untitledHint: introduce default for workbench.editor.untitled.hint
98d129e8b9f firefox: do not use ctrl+shift+P for show all commands since it is taken, make sure F1 is rendered
3cca5540aa8 Do no install repo on Raspberry Pi OS (#118826)
c4fbdc32275 accessibility: 1000 page size as default
393adbd3971 fix #118970
61e44238a28 💄 process use
393cc7f4a22 debt - consolidate process usage
cf439681f6f multicursor aria polish
ae510aec2a7 no indent after 'source' tag: for #118902
fe1264b0f2f explorerModel: add toString to explorerItem for more precise error message
094274f0d1b Don't show select default shell when proc support not registered
d1bffb783a5 Merge remote-tracking branch 'origin/main' into tyriar/118066
a4adb60e883 Add "Copy As..." core submenu to editor context and Edit titlebar menu (#118212)
11b1f937eb1 Prioritize port label from setting Fixes microsoft/vscode-remote-release#4542
2ac67ce84c4 fixes #118951
7a55f6fed7a skip failing notebook test
3f81fd64303 🆙 distro
e8c71c048fa use %~1 in bat files
c7a86c07979 🆙 distro
68a252ea778 environment - depend on product service
eb90b1c59c6 sandbox - extract IPC based file service (client) and improve runtime behaviour
f241e2e26ac debt - inline deprecated amd.ts methods into tests
8f1b7a36def sandbox - allow to reuse environment service in sandbox
1441ba91f0e environment - consistently handle VSCODE_CWD in all our node.js processes
56ee90e32e3 path - never use fs.promises.realpath
3d626dd868e Use "%~1" instead of "%1" in bat argument parsing.
640fa1af29d debt - use product service in more places
0e05a1f21a1 fix integration test
819cb01e0e0 make notebook integration test more stable, fixes https://github.com/microsoft/vscode/issues/118889
84fe402d655 Improve getting started page - Allow clicking checks to dismiss items - Allow hiding categories
e05ab31f373 Clean up styling when contrast borders are defined
a90759b5395 fix build
3006ac8e940 try out multiline extension view
5ad7633c4e9 fix scrolling body for workspace trust editor
809e11134c1 fix css for extensions grid view and settings
1a5d7f4f8ed Merge pull request #118482 from microsoft/rebornix/nb-list-focus
b81cea2a350 Fix Emmet abbreviation for Handlebars style blocks (#118832)
257fbae3f34 Ensure editorContextKeyService on markdown cell gets disposed Related to #118782
e1f84e38ab2 Ensure markdown cell editor is disposed Fix #118782
216bff57715 Merge remote-tracking branch 'origin/main' into rebornix/nb-list-focus
eac163c0611 fix tests.
c1f954ce48b optimize scroll view from bottom.
5af4ccb87be copy cells with multi select.
ad7983834af extract clone cell.
34a537bb732 sort numbers.
162d08892db Clean up
569aedce014 Mostly working seamless relaunch
7806efac02a tests in webworker EH
ffdef6b9be7 Fixes #118759: Render a separate span for each inline decoration
458904ed7a3 move cells with multi select
e545c0750b8 copy paste with hidden cells.
17beaf29fd5 Fixes #118614: Clear any outstanding state / requests and fetch semantic tokens when the language mode changes
8ca6a56d467 Try restoring ports more often Part of microsoft/vscode-remote-release#4551
d7622d392b4 change back untitled hint default to be hidden
edf387a2e8f run filename through realpath because it seems nodejs isn't always doing that, https://github.com/microsoft/vscode/issues/118812
1c9e7eb296e 💄
5a8936ae639 Lift native text file service to electron-sandbox (#118815)
1bb87db91d3 debt - provide groups merging from service and add test
0b4915dcea2 Change portsAttributes others to be its own setting
61fe79db654 Remote indicator for folders and workspaces from contributed file systems. Fixes#118813
55bfe8c2167 Merge pull request #118766 from microsoft/aeschli/extensionDevelopmentKindSimple
5109a52b2a6 explorer: use findClosesRoot in select()
3aca77c0161 Merge pull request #118777 from jeanp413/fix-118557
3eae8534747 fix #117093 update Filter on Type indicator after 'list.toggleFilterOnType' command (#117099)
9d220a95c1c Fixes #110885: Have `--max-memory` also be applied to the extension host
bd74e2fb6a0 replace openOnFocus with selectionNavigation
5f451c6670d Merge branch 'main' into aeschli/extensionDevelopmentKindSimple
1f22e55badd sandbox - share most desktop.main code
d6d2910b96b sandbox - use actual workspace and config service
1dce5d35536 replaceCells as a single edit.
ebc6eade483 update prefix sum always when edits happen
fe9466a6e1d false negative hidden ranges test
4f5824ea28b enable async tests.
3dff030ea14 delete folded cell would not change other folding states.
5e2f573d1dd cut multi cells w/ folding.
06b54543d66 Comment out a few error logs for now
498449fa8c1 Remove content version logic from webview
02d3ca91dc7 Make sure we update cached version when cell changes
544b117130a createMarkdownPreview should only create previews, not also update them
1e92de9921e Log errors and remove unused method
574740fed37 NotebookEditorWidget should not have to know if a markdown preview already exists or not
b5e22e7ed43 Remove extra log
6ea4b1cdc1a Add version to MarkdownCellViewModel
97314005fca Revert move change and disable debug flag
aeb8f3811d6 Avoid re-rendering markdown cells if they have not changed
4b9d29ae6b4 more polish and re-use extension grid
d5f47dfb885 Notebook custom markdown renderer optimization (#118288)
3635f113876 💄
b4ebf03316c selection tests.
0dcf9300ddf Fixes #118557
e9b7b5d25b8 configure extension kind of extensions under development
63d6e0c008a adopt selectionNavigation.
46fd12b0a91 align selection and focus if they were both empty
d31566b57f4 Don't include css in main katex bundle
8627fd1f883 Merge pull request #118753 from microsoft/alex/extension-test-running
a97990c9713 sort indexes in cellIndexesToRanges
919292a6742 Merge remote-tracking branch 'origin/main' into rebornix/nb-list-focus
ae4ffb1b81e Handle extension test execution on the UI
52ab2fe123f add Education extension to category constants (#118589)
ac0008a25b8 Remove waiting for welcome page while we are experimenting with what the welcome page will be Fixes #118748
8f8321d638d Smooth relaunch poc
d574f8e9163 remove duplicate code
63460db67ea Fix #118741
d5e4525830e Add comments to add java workspace tags to GDPR inventory (#117740)
1ad8c467972 Merge pull request #118574 from microsoft/tyriar/100709
5afac656035 Prevent double attach to pty host listeners
ba8f0fff7ca Remove logs
b92b610e861 mark isEmpty as readonly
f2515c57a4d Fix repository link for vscode-references-view
bc405e936fd Try new CSS grammar Fixes #115480
244428dfa7a sash: workbench.sash.hoverDelay setting
10fc457d699 💄 sash
f8ce2745c05 add stdout and stderr mimetype, add renderer for stderr
97efcde244f Merge pull request #118664 from microsoft/aeschli/extensionKindController
3fb39ad72d6 fixes #118694
bd84f143797 Merge remote-tracking branch 'origin/main' into tyriar/100709
37a826fe75d Open Recent goes to wrong workspace from remote. Fixes #118683
6af126bb3ce Move to writeSync instead of writePromise
49cad9a1c0d Fixes microsoft/monaco-editor#2382
0740b4a3134 sandbox - move platform limits to common
fdd57917f30 don't mixin default metadata when "replacing" notebook metadata
9a982d0049f fix configuration caches - respect scopes
d7854c3914c Remove unused
8788d628814 First cut of moving to hybrid getting started/welcome editor
9b2ee7fb7d9 Reduce size of Katex bundle
da3cbe74dce Avoid extra postMessage call for iframe based webviews
8fefa6aff22 Speed up mac builds (#116984)
984479d1792 Fix not being able to run a cell when it is in the Success or Error state
07d02d3e2b1 use new icons
638926d5b5d CES experiment treatment
2d7fdd82ec8 update connection state before reconnections
f3f1c131385 Update Codicons: add trusted workspace icons 1f495f5857
b1b80801806 Avoid some calls to `.then` for iframe based webview post message
5b5dd906551 Fix manually providing PAT for GitHub auth, fixes #118675
11d5e82c80c Fix any key causing shift+tab focus change
c72d7612b41 Add an untitled document data property (#115790)
371562f630b move trust color tokens and update values
e679983a3fc remove border, use color icon, use link button
1f2313b4a2d Add back custom editor test workspace
0f6d7c41eb5 introduce customEndpointTelemetryService
268c0d04a66 fix #118578. offsetHeight to include padding and scrollbar.
d1db6f0efef notebooks: update output to match NodebookCellOutputItem api
7cae7b5cedf add ExtensionKindController
a2b5e58b091 remote authority - update comments
75da06499c2 #101995 extend tooltip of menu item that defines 'alt' command (#116211)
3ac310d1cf9 Remove icon from input row in ports view
3dc05e36e15 list: anchor trait
913a5949445 cleanup debugHelperService
f1f830aefa2 Fix User tasks only working once without folder Fixes #118370
27ce1eb630f list, table: selectionNavigation option
6be4a142367 fix https://github.com/microsoft/vscode/issues/118609
8fd24025701 :liptstick: deep freeze notebook events before emitting them
6c6db188b7a polish, avoid classname.split('')
f0c44394d11 Merge pull request #118433 from microsoft/aeschli/openWindowsWithAuthority
637b659e4ad refine NotebookCell API
afe0e2b9a77 Fix regex port attributes over applying
278a41c349b Show Open Preview in Ports view for public ports
a6d7d86e857 remove `viewType` from openNotebookDocument call
da562fa27c5 Add regular expressions and "others" to portsAttributes Fixes microsoft/vscode-remote-release#4623
b3e6307430d polish
1422de11110 sandbox - move performance.contrib to sandbox
abea343c10e fix https://github.com/microsoft/vscode/issues/118369
b0f0b6125dc implement review comments
23e0d141edf Update src/vs/platform/windows/electron-main/windows.ts
d383642ba20 Update src/vs/platform/windows/common/windows.ts
78224b9b9e9 refactor perf contribution so that they can be inside electron-sandbox, https://github.com/microsoft/vscode/issues/111211, fyi @bpasero
f83b2f46dee shell env: add more logging
1d6241a8a08 prefer ReadonlyArray<T> over readonly T[]
94303f8e574 build
256ce60286b Bump elliptic from 6.5.3 to 6.5.4 (#118478)
623075e0962 update distro
a713ca6204c Merge pull request #118596 from alienvspredator/main
420f8dde79f debt - more layering fixes
f0321e30875 debt - layering fixes
9d8042db309 more jsdoc around workspace concept
a19fac2442c better docs for #118566
96fabf5cf95 fix #118591.
6d079845776 fix(typescript-snippet): fixed "newpromise" snippet
1d686afe81c reduce grace time of remote terminals (#118571)
a9087e9d0a9 Try to avoid extra promise chaining for posting into a webview
cbacbe647c3 Fix markdown preview still being rendered while in edit mode
54f30ed19ce Lock to commit rather than tag for Azure login action
3244facbbbe wt editor stepping stone - make extensions list better - centered header style
d4ee684c8de testing: show progress in status bar, minor refactors and cleanup
80112e79ffb testing: show total number of tests to run
5b41604444b testing: add more logical default autorun behavior
7a9e144ee15 Fixes a listener leak with ILanguageSelection
57155e84203 Fixes #118195 - avoids update if already set
bcb8c8a4f4b Remove notebook document runnable metadata #106747
8454701b67c Update test for api
225a8c2b89d Infer cell "runnable" from notebook kernel state Fix #106747
7a19d09047d Begin eliminating cell runnable metadata
d1164661d29 Fix markdown edited cell height on reload
c77e5ccd947 Add back top margin for webview cells
d299be88ea6 Updates proposal for #116906
556e6d8310f Fixup search smoke tests
58bd8e075a3 Fix spelling in comment
ba54c76164b Use TS replacement span if returned
724bc08f906 Remove log
f2d687752c9 Create a new pty ready promise on relaunch
65e4309c0d9 Directly expose environmentVariableInfo
37c54c79e0d Fix compile
7f94f0d97c2 Move some ptyProcessReady usage inside proc manager
3cc479953ca fix #117718 fire onDidChangeResources event after unregistering group
a7c9230fb33 Update distro
d6f4353fae4 bump distro
9eceb504987 Move label about for #115244 after more tests are failing
f8a6f90dea7 Revert "chore: bump distro"
e5a10ca55d6 Skip search tests while diagnosing flakeyness
88655de6104 Adds logging
6922f6150d8 xterm@4.11.0 Diff: https://github.com/xtermjs/xterm.js/compare/a73fe62...4.11.0
79e2119c5e6 Revert "snap: set compression to lzo, #117852 (#118116)"
43ced8a10a3 chore: bump distro
0f042b2c856 fix https://github.com/microsoft/vscode/issues/118569
0e43220113c finalize telemetry enablement api refs #110267
95d3c1e63b7 finalize isNewAppInstall api refs #117058
e60b94d6e9c Merge branch 'main' into digitarald/ces
6438e0564af Add 'Marketplace' as option for file on and remove as top-level type, #118473
17c67963f32 api work snapshot
112bd090027 Queue file operations
4ee2ef41e5b update cache on reprocess
0f64ef1b655 remove NotebookDocument#contentOptions
f0cf34e073b debug: do not bind F10 to step over when on web
eaf4a6a91b7 Fix debug console URI being decoded (#118226)
417b7803a18 Update distro
2c11dafcc2f Merge pull request #118252 from microsoft/tyriar/116467_2
dc92ff53548 Set distro back to that in main
4bb960ade60 Merge remote-tracking branch 'origin/main' into tyriar/116467_2
b02e102f480 untitleHint: use expereiment service
90efd0a81aa Update README.md
449158a1aa7 Some Ports view cleanup
b8a320867e5 allow null for remoteAuthority in IBaseOpenWindowsOptions to force local window
637497076ac Update distro
1e7fbfa7674 Merge remote-tracking branch 'origin/main' into tyriar/116467_2
e7b0596d89a Revert "Comment out notebook compile error"
aaf6287eccc remove skipped test
e96f0ea3700 todo-tag
7bcec044268 Comment out notebook compile error
878526839a3 Update distro
364b9e98e83 Merge remote-tracking branch 'origin/main' into tyriar/116467_2
ab9e11f38e6 Remove resolved comments
e2ba7c6ae30 Breakpoint inline edit button should be a submenu
27efd88041d Remove preconnection terminal concept
4db71714ebd Properly dispose everything in tunnel view cells Part of #118544
9cc276648eb remove onDidChangeCellLanguage-event in favor of the existing document closed/opened event sequence
55af8021a12 Simplify RemotePty, revive shell config cwd
e373b9c59e2 Focus row when escaping input on Ports view Fixes #117771
3c96cb6254a Merge branch 'main' into aeschli/openWindowsWithAuthority
99e97da512b revert unnecessary change
d1dbb93317a Remove remote test failure comment
6d01ad952a9 Merge remote-tracking branch 'origin/main' into tyriar/116467_2
e15767f6dcd add comment for remoteAuthority
5ce792fcfad Add SECURITY.md
98a22a957a2 declare cancellation support for openNotebook and wire it up, exempt notebook content provider from provider naming rules
0e04c15de4f assert unsetting of active notebook needs null, https://github.com/microsoft/vscode/issues/118470
bcfcb539ab5 unit test for https://github.com/microsoft/vscode/issues/118470
8c436826ae5 Merge pull request #118471 from DonJayamanne/openNotebookBug
30d699fa104 on fire active notebook change event when something changed, https://github.com/microsoft/vscode/issues/118470
425316c3764 Add a compose language (#118042)
63be79e67de Merge pull request #117062 from NotWearingPants/bugfix/rtl-cursor
edfbf27e3af #118443  - change name
fa6d38a99b3 change nls ids
9d3a1d9f59c Fix #118443
6b76fcb671e Merge pull request #118468 from spetrescu/main
7d96db1e51b Make underlined link buttons blue to match the styling of similar buttons
27975dad4fb move to IProcessEnvService where appropriate in default shell logic (#118271)
ac229ced073 Revert "Reenable smoke test to see if still flakey" #115244
09c3c2d3be4 Remove broken part of test
11a84a6e8ac inset -> output.
b62e3c7d1db Update distro
5fdbc82111f Re-enable task and term test
9878ccfbd74 remove markdown preview only when it is hidden or deleted.
250c7baf7e8 Fix #117903
c870a55b708 Update terminalProcessManager.ts
8fe29a7c415 Uncomment in test
30f41631849 Skip the failing test for remote only
d89e8cd27ce recent entries with authority
c59c1101162 revealView should scroll a little to reveal items below viewport.
d4f8348c6ac Handle undefined extension publishers in issue reporter, fixes #118480
61301530c69 revealView should scroll a little to reveal items below viewport.
23ad719498b Log acceptTerminalOpened
bdbf5850127 Bump vscode-emmet-helper, fixes #118363
0e8fba32637 Add outline offset for view actions (fixes #117349)
9b1700a8291 example of notebook specific navigation commands.
2c1037d3521 Fixes #117600 (#118397)
b20839c1f3d Add 'Marketplace' issue type to issue reporter, closes #118473
a8739f9c3a5 Change messageDisposables to DisposableStore
2b9470cb4e1 Clean up SearchView link button code
31a7757fc7b Better "Open Settings" option in search view
18f16643ead Add button to reenable search excludes Fix #115352
244e9e6e793 set remoteAuthority in NativeHostService.openWindow if not yet defined
1761ecec3bd reduce selections.
b6b9aa15ef6 debug: allow passing partial config to start debugging command
221e20b3742 Re-enable, add some more test logs
7e6d4c5eb91 debug: fill in selected configuration by name if not provided
3f56118e7bb move cell up
a39e7343653 Oops
584999658ee Bug
820f0eeb270 Fix tooltip not showing for codelens extension
a0c8d41f9ed add notebook navigation commands
78cb4cfc32b improved comment for InlineValueContext.frameId
3df01b4ae74 Include ms in shutdown constant comments
45c032da7ab Skip the failing task test
1469a82540f fixes #118006
d8a7202293c Update distro
e22c2be14d1 snap: set compression to lzo, #117852 (#118116)
03c8548523f Merge remote-tracking branch 'origin/main' into tyriar/116467_2
9022c7fa945 Update distro
f2cfdcf19b8 Bump distro
4a82fbab162 Don't force create a terminal on no reconnect
06044789bfa API proposal for PortAttributesProvider (#118446)
3f778f6aebf Update distro
9c78fa40ca7 skip failing test (#118443)
20b19612917 Move proxy resolution to vscode-proxy-agent (#117054)
b41b95faee9 Pin windows-process-tree@0.2.4 to match main package.json
4d3b1580233 Disable terminal tests in remote again, fix settings for tasks
1cd624c12a3 Merge remote-tracking branch 'origin/main' into tyriar/116467_2
4abc244a97e Add windows-process-tree to remote deps
c2a92a1ba67 Merge pull request #118418 from microsoft/ben/sandbox
caed3ea183a Merge pull request #118269 from davidanthoff/julia-indentation-rules
007baec8d51 fixes #118214 (#118425)
c187999ee44 Merge pull request #118310 from smorimoto/ocaml
2a0f9aa8dc7 Reminder to compile between tests
69d36e8c982 Fix transformToSnakecase
305456c873f bump distro
f7274905565 editors - fix mergeAllGroups (#118268)
8c3a00f78cb allow debug textmate in sandbox (#118219)
f74d3b2fc75 fix tests
0c17e384499 sandbox - migrate backups from md5 to our hash algorithm
dbe9dd49675 sandbox - make signing and integrity available
3f46e7f7b59 add ui flag to mocha tests
74532eb261c Re-enable process unresponsive checking
5cc1775bbf0 Disable unresponsive create process
11897d00a7a Disable pty host listeners temporarily
074632a51f1 Try enable remote terminal integration tests
508fcfbb537 Add more OCaml related file extensions to the OCaml group
5d80c30e5b6 Reenable smoke test to see if still flakey Ref #115244
74014e7fc6d Fix #117251
fe79bb261fb Add defaultSnippets to getting started contribution point Closes #117476
2d5e9cae4e0 💄
d3086eaa8c5 expect commands to set selection and focus for us properly.
7707feab17b accept focus from the list view.
6e83ba82107 fix #118279
da79b9db816 Don't setup pty host listeners twice in remote
ea5f05a4358 Trying to clairify how webview options are used and passed around
e066c74761e Document new fixedChunkSizePolling ts watch mode
d7d42534260 Mark field as readonly
a01035c44f8 Pick up latest TS 4.3 for building VS Code
02a5d5925ba Disable relaunch in tests
755fae50ab5 Bail out of create process if it's been disposed
2d3f1a0b478 fix #117699
258ee03bfbe Update distro
3483e9541b2 update betweenCellToolbar actions per context change.
61ea6ad847a Remote shell type support
fc677cb3220 fix #118273.
c40b367840d Merge remote-tracking branch 'origin/main' into tyriar/116467_2
b15bbfa8516 More test logs
3e345101dfd update shellType when it changes for local windows terminals (#117998)
6b2daa9a897 Update distro
ff09362f443 Merge remote-tracking branch 'origin/main' into tyriar/116467_2
5d5fa588828 Support pty host management in remote
29b1fcffd1b fix #117684.
7af259ab841 Add logs to test
c24bfc336c2 💄& localization
daf840b9293 Revert "fix visually background flash of cells."
016b809eef0 kill terminal process on ipad (#118247)
c18378655bd Add Julia indentation rules
7f7e427d3ba fix visually background flash of cells.
f704f80f877 Pick up TS 4.2.3
22cb8ccdac3 Merge remote-tracking branch 'origin/main' into tyriar/116467_2
a7d9285b89f Update distro
2e68f2ae918 Better fix for #118235
00d3831d0c7 fix #118248.
59972ff745f fix build
5144d664926 dedup ansi color rendering.
bba6d12ccb2 💄
ff5da2ff172 DOM.show/hide.
d2e39d0ae09 use resize listener for all main frame outputs.
32f7c1d93a8 Don't assume uncompleted category exists Fixes #118235
ccb3601d552 Support term cli commands
c2e3a4cdc67 Update distro
af0ec1caa0b ctrl+c on ipad (#118243)
6799395da0c Revert "fix #114009" (#118242)
dfbc5374637 Increase local grace time to a minute
fe24a792b03 Support attach to session in local
f916e9f1aba fix #114009
df6b2691705 Support orphaned processes
48be13acf8e Check if VSCode runs serverless (#118233)
e518e533653 Share IOffProcessTerminalService
51e773e69f2 Merge branch 'main' into aeschli/openWindowsWithAuthority
0bcba0486bb Make setTerminalLayoutInfo interface consistent
7703dff5fc1 Clean up, bring local remote interfaces closer
92ad349125b fix typo in comment
aadc16a2371 Simplify channel comm
230e0fdc9aa clean up, some ground work to support viewColumn, $acceptEditorPropertiesChanged must update all state before sending events, remove active notion from notebook editor
9516844abfd use TS typle naming feature
68a6f1c30e4 look up editor by id, slimmer dtos
f7ff53d7b06 Remove `_wrapWebWorkerExtHostInIframe`
418b8248e43 Progress towards sharing local and remote term impl
25dc50c18ed Remove start-up timeouts
49b5e3ba0ae bump version
978d1399f54 Fix compilation error
fca9c7f78fb Fixes microsoft/monaco-editor#2375
5931e598b10 Fixes microsoft/monaco-editor#2344
205ec8c5f2d Fixes microsoft/monaco-editor#2358
b2a0913ad23 Fixes microsoft/monaco-editor#2168
9748b5f3c0b Fixes microsoft/monaco-editor#2359: Avoid syntax that confuses webpack less loader
5c4663baadf Fixes microsoft/monaco-editor#2355
60222b710d4 Align `MultiEditorAction` with `MultiCommand`
453e2793b2b Prefer using TS constant defining the context key
04770364fdc #118222 skip failed test
1260de1c101 sandbox - move workspace tags to sandbox
17212ee46f8 #118199
c024db9f419 NotebookEditorSelectionChangeEvent should contain selection ranges, not cells
2e84eb92077 explorer tests: use strict equal
1e28c1ec7ee debug tests: use strict equal
1a9df6127cc fix smoke tests
ef6d44f53aa debug console shouldn't collapse messages when they have different source locations
6e5e1e700b9 api todos
6117524374f make NotebookCellData and NotebookData classes, rename NotebookCellData#cellKind to NotebookCellData#kind
86df4442128 remove todos
3a21f7815c4 Merge pull request #118125 from microsoft/sandy081/keybindingsEditor/adoptTable
57aaafc72f3 Do not check for settings sync enablement while initializing in web
d4b5298cd62 -add bg color to even child - clean up
997c9f29307 add showNotebookDocument overload or uri
ae2f3e07e12 streams - add test for using error as data
be70750f862 comment 💄
b65719bfa27 streams - require explicit end() after error() and remove error support from end()
188e6aac851 stop the code bunny, reuse the createAndFillInContextMenuActions-util, fyi @sandy081 @rebornix
7386525c683 remove one more occurence of '1_run'
bc62648b05c Revert "Remove authentication provider package.json declaration"
fead22bae42 bump distro
eed8a79e81f Extract proxy agent support (#117054)
79096af4755 use CSS for odd styling
223f4f820f8 multi cursor: announce cursor changes
3b05017bb8e more 💄, more strict typings
1d8493b203e 💄 in mainThreadNotebooks, return types, more private, dispoable store, duplication removal, etc
81edf8b91ab Merge pull request #118071 from mtaran-google/main
85c1a17b60f Merge IEditor and INotebookEditor, move editor things into notebook editor service
fc785836967 fixes #118006
d84ddcbd529 Open window with authority
39c1d680867 #62531 clean up
2dfc39c6949 Remove arrays#mergeSort because by now browsers support the refined sort spec which mandates `sort` to be stable.
587274078c1 remove NotebookDocumentMetadata#displayOrder, https://github.com/microsoft/vscode/issues/117684
3e8b0eb2d4f remove displayOrder from NotebookDocumentMetadata API, https://github.com/microsoft/vscode/issues/117684
afae25919a8 Merge pull request #115351 from gjsjohnmurray/fix-62531
fa37b721d1e 💄
ddb17dc1282 💄
dbbf2b16882 shell env - introduce a service to resolve shell env as promise (#108804)
bd2b229870b debug: update js-debug
567b82a0f9c Reduce padding of new markdown cells in notebook
38ac13bc833 Slightly reposition the folding indicator for cells
99f2b830a1d Improve drag and drop indicators for custom markdown cells in notebooks
354a0a2620f Disallow dragging the outer markdown cell for rendered markdown cells
a34ed4b0d7b Make markdown cells span full width of editor
60d600b3661 Fix showing wrong name for files in search after rename Fix #117778
1c7ced625a3 Update dimensions of webview element when it is shown again
72995bcb80b Mark property as readonly array
28b7345808b Improve documentation for WebviewService
9fa1800b979 Make the webview icons manager disposable
5bff5459d13 Move webview icons from generic webview service to the webview workbench service
acdcb64a6c9 Throw error if a webview is double registered
487296741f5 Don't  require lazy webview to be passed to WebviewInput
344f329dd42 Make reviveWebview take an options bag instead of parameters
79ff1ec91bd gate on feature flag
aca4cb12985 workspace trust telem
0f975049421 Fix output padding/margin for diff notebook editors
9f395ddb934 Update Codicons 7e0f377891
0eca51a2dad Mark selected markdown previews in notebooks (#117947)
191d3324132 Add offset to button focus (fixes #117909)
8a81f4149d3 add warning log if webgl cannot be loaded
6abc478020f Update src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
8b1ddde4f5b move disposal to end so measureRenderTime gets called
920b8b31931 store suggestedRendererType to avoid retrying webgl if it's thrown an error unless the setting gets changed
e9a748131c1 use storageService
bab447271a3 measure render time if webgl throws and canvas set
b619d92639d use canvas if webgl throws
e7ce70318ff after webgl is disposed, don't retry to enable it unless the renderer type gets changed
ca83d009f37 Update src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
d61adbfd923 part of #106202, make webgl renderer default, using dom if loading the add on throws
1e5e33cd023 testing: fix unit test err
d6b3bc68f1e testing: move types to classes instead of interfaces
35aed337263 testing: improve RequiredTestItem api
1370dacbe0f Rename localPtyService to ptyHostService
05ccfc4fcb7 Move localPtyService to node
db06103f1bd Enable search in open editors checkbox by default
597c5958527 fix overflow in command column
0150b020a10 Merge pull request #118121 from microsoft/tyriar/116467
2d4e671f730 update distro.
5b2865bc99b fix layout - do not consider header height
c6202bb3cc5 Adopt to use new table widget
dd3f3f9d7fe Update issue scraper to use standard bot PAT and run every month
8465489bbd4 Fix unit tests
8fd1b977166 Merge remote-tracking branch 'origin/main' into tyriar/116467
12ab47ff863 Fix compile
c9ae209c80e Use safe process env from electron-sandbox
97cb1ff41d2 Register ILocalTerminalService
468d73edeb0 Fix compile
306bebf0f15 Move responsiveness check to local terminal service
3a1f4c402b4 Move terminal instance service methods to local terminal service
df863f912b3 more context key doc
5ba5f986b92 remove notebook dependency from build edits
128e9b502d2 add frameId to InlineValueContext
cb7ad05cb7e Merge pull request #117766 from microsoft/tyriar/remove_flow_control
73fee061714 Update distro
9bf3a06e647 Merge pull request #118118 from microsoft/tyriar/117990
68a3a7bbf9b improve comment
0ef6619a3eb services - use refineServiceDecorator for environment (#117881)
1e0d5009b5d fix exception breakpoint padding
03681b39a50 Update distro
fa4c3c6cf1e Show ports badge on view, not view container Fixes #117904
a5c28d0ca06 Merge remote-tracking branch 'origin/main' into tyriar/remove_flow_control
ddd6fccfee0 services - use refineServiceDecorator for layout service (#117881)
ffa703d4805 Recover on pty host reconnect
c0f6549d1cb files - address #118060 on master
94dec183740 Fix simple file picker not opening entered value Fixes #116858
7586d1a0fc2 Fix extra http on some forwarded port addresses Fixes microsoft/vscode-remote-release#4595
fb46801cf2f lock file-changes-action
dd14e280254 Don't use an icon on the Port add row
c2a2cc2bc3b Allow quick input to show info severity (#118032)
179c89852f7 Change icon for npm scripts view Fixes #118019
3c238e71dbc Add "hasPackageJson" check back to npm view and let it find files in directories Fixes #117950
1d46693af84 fix IThemeService decoration ids. For #117881
31012ea2d4a add refineServiceDecorator, https://github.com/microsoft/vscode/issues/117881
978b0d6ead9 context key doc
16ea2f2894b remove "getter" wrapping for proposed API types (classed, enums). These checks needed to be disabled because of an TS issues
f79a0df4dbe api todos, remove long outdated proposal
01d775756c7 todo goes issue
b6141474a76 move undo/redo and clipboard support out of notebook service so that it slims down
c349764ab2e no graceful, throw errors when trying IO on notebooks that have no provider, move notebook model things together
069da883da5 Merge pull request #117834 from jeanp413/fix-panel-codicon-outline
8025d97ece8 mark `displayOrder` for removal, https://github.com/microsoft/vscode/issues/117684#issuecomment-790019754
73c01a5dd87 Merge pull request #117424 from atscott/dedupereferences
f43fcbe6a4e fix https://github.com/microsoft/vscode/issues/118103
62d6a24efb9 revive URI when receiving them, fixes https://github.com/microsoft/vscode/issues/118085
0657df6e82f fix some area labels in extensions and scm
534e2306379 Renaming a folder adds it to history (fix #118080)
2ba67b7b075 Allow ripgrep search provider to work for files backed by file scheme, but not file scheme themselves (vscode-userdata) (#118069)
5f17dc2a596 Ensure that PrefService calls openEditor with a proper options object and add tests Better fix for #117952
54758b7e16d Revert "Ensure that PrefService calls openEditor with a proper options object and add tests"
2ae55bc7164 Ensure that PrefService calls openEditor with a proper options object and add tests Better fix for #117952
16c94f18258 Remove incorrect command
a4b2541e379 Mark disposableStore property readonly
584d2338870 Use `_register` for disposable
538931e7906 Make sure context key listeners are disposed of
49d05f998f0 Add `CodeActionTriggerKind` api proposal
20f06e04445 Clarify docs on CodeAction return type
7e18b7006d0 Use generic type for CodeActionProvider
ba117e60c20 fix #118043
4bd99a42df0 Fix old markdown preview not being removed on drag
4371e72fb6a Fix potential null exception while dragging cells
abf99de040e 💄
aaf70523a8e Bump vscode-emmet-helper, fixes #118008
828f99eff55 Update diff editor with new webview options
e56182e67f2 Make the backlayer webview span the full width of the notebook editor (#117948)
bfa7822f703 Fix typo in IWorkbenchExtensioManagementService
e9533c22fee add basic workspace trust unit test
19b7444ccf0 fixup! fix microsoft/vscode#117095 de-duplicate location results
17f63a649ec testing: update to more proper provider api
2f7438f492f Fix spelling for type
5d5b9dd0a8b Don't label non-editable custom editors as readonly
5f24ec84ac7 Use correct new context name
6949fed6ed2 Update grammars and fix julia update script for Windows
0e94794c9d0 debt - remove unneccessary indirections from notebook service
09149ac0930 Avoid double dispose of pty host client
f80f0d7074e More forwarded ports trace logging
65c0eeb03d0 fixes #118006
a24cb4615a1 debug debt: remove unneneded check
341c130b0e9 call stack: get rid of actions, menus everywhere
fd948827992 Deprecate editor.accessibilityPageSize setting
79cf4e92ce1 Use Promise instead of event
14fd07d57a2 Workspace trust api feedback
65a9aa17768 Use "(Settings) " as a prefix for userdata paaths in web Closes #114979
c3d7bd2269d Reserve space for recent list to prevent shifting when it loads Fixes #117628
e21f3916af7 Focus first uncompleted category rather than whole document on start Closes #117540
09dae2618ae Disconnect in debug toolbar should dispatch to root session
8c13b011133 debug: simplify registration
b6f87905932 💄 comment
4def740615b wrap perf stuff in iife, https://github.com/microsoft/vscode/issues/116546
bc444ac3797 Fix #117869
bede292addb Error on `remoteAuthority` in Local Workspace File. Fixes #118023
6b3313141de make sure local dispoables are disposed and cleared, https://github.com/microsoft/vscode/issues/117675
d13b7ff3641 one class, one variable style, https://github.com/microsoft/vscode/issues/117675
2e9fde23fdd add todo-tag for InlineHint, https://github.com/microsoft/vscode/issues/105690
0a49559a443 Mitigates #118008, better fix TBD
a795f49b097 more enforcement of readonly nb doc.
62cfd68c779 absolutely no polish POC feature list
d82bb46c445 do not prompt for confirmation in editor
ed94b5d7562 allow text selection of description
6979a39169a move webview resolved state internal.
c113b806cca re-organize notebook editor widget methods.
1614e28a11c remove notebook editor widget methods not used.
c70fb23a27b 📓 move decorations out.
52bce12c25e testing: fix up wording in api
25b5db4d55c testing: make workspace test hierarchy required
94cda08af53 testing: make runTests required
9fbc8811428 testing: make hidden state more clear
2cc1a8061d1 Fix VSCode spacing
cf3faa40460 Don't relaunch extension owned terminals (#117987)
6c6caf678fe Don't force kill ptys on Windows on window exit
7b91cd85284 less exclamation
6643b5e520b de-dup: uri.
0eb8c53f90b de-dup, NotebookEditorWidget#willDispose, didScroll.
623741272a2 Add activeCustomEditorId context
08ceea18aa0 rpm-spec: fix the wrong claim about working on EL7
e3829dc2477 Add 'prune' option to fetch in git extension API (#117923)
975dfff6db6 Emmet: Change the type of emmet extensions path (#117946)
cc5db258239 testing: fix NaN if 0 tests ran
fe353a54240 testing: close error peek view when test run starts
7d1751444b2 testing: fix tree view overflowing container
b6251fc0baf testing: fix 'run in current file' running all tests
da98cc6e94d testing: fix run at cursor discovering indefinitely
7c1305782b1 testing: adopt new autorun icon
4a6488c6d03 Move kernel/execution code out of NotebookEditorWidget for testability
b629d888ca6 Bump Emmet yarn, fixes #117154, fixes #97632
5073e6f1fe5 fixes #117968
f97dd62ece6 Make sure we use the cannonical uri for file move target
1155803d134 Use case-insensitive check for file extensions
bb8b693479b Mark properties readonly
20ec5b80085 Reuse generic open with logic for custom editors
75b5207f850 Extract BaseToWebviewMessage interface
4e4c43f30fd Update distro
e994e5ab498 Persistent terminal id -> Persistent process id
647773d7e68 Rename terminal id to instance id
88d9e2b46b7 Refactor second task test
f8c41a80b0d Refactor first task test
c8fc575275d Ignore terminal events not related to task test
e62bf133c45 fixes #117575
15c02651811 use one element for focused/active item in actbar fixes #117584
cd9ce538ba5 Add shouldPersist terminal tests
c6d6bda7197 Merge pull request #117974 from ko1/patch-1
20096095f19 fix extension readme not rendering img width height (#117961)
2b50ba174f3 refs #117960
5d4377de987 March for API issues
72de8e9be86 add region markers to isTelemetryEnabled proposal, https://github.com/microsoft/vscode/issues/110267
ff225b9fcce add telemetry enablement api (#117944)
4de8cb29073 increase accessibility page size to 2000
9692037daa9 Update vscode.d.ts
9e4520310ed Fix remote terminal reconnect
85cbc2bc7ce cancel parameter hints when editor blurs, https://github.com/microsoft/vscode/issues/115265
44955421ae7 fix https://github.com/microsoft/vscode/issues/117431
7bc94131f17 change anyScore so it repeatedly run fuzzyScore on substrings of the pattern, https://github.com/microsoft/vscode/issues/116683
0018625d00e more details in explain dialog,  https://github.com/microsoft/vscode/issues/116683
e2c5ff9db00 do not auto open pasted file
2022aede921 Return early on promise reject.
ed1118b27b1 Support empty messages during location import
58ab537f4fc Debt: descriptions/hide context keys (tree, ports, tasks)
66b7ffaabf9 simplify  $tryShowNotebookDocument further
65e28321240 use label service to infer name of notebook input
83f40886812 notebook - simplify group/viewColumn handling when opening a notebook editor via API
df8763cfff7 api todos for notebook cell
be11cb2de00 disable failing test (#117446)
f70433a596a fixes #117910
73f9f126fb2 fix tests
932c7e247dc 🆙 distro
8c1bfcb569a services - distinguish environment services (#117881)
5510ee9c51d services - distinguish layout services (#117881)
6c13c8f4ed2 de-deup: getContextFromEditor.
9f7d229461a Extract decorateFileEditorLabel to a common function
d7f90c7dbcf re #114554.
d9d5e5d9c38 Merge branch 'main' into digitarald/ces
e3bc5abc511 Draft for ces survey
400737c5b89 Pass 'data' to completion details request (#117092)
5d6ea08985d fix #116751.
01025340392 Splits clone/docs welcome Allow GitHub Browser entry in the middle
015ca030c4b tests for selections for navigation and hidden ranges.
177e3474c5a consolidate index/handle update api.
1f08b8f9024 wrong use handle/selection
460ebdaaf5b Aggregates welcome view registration by view id
9d071596951 debug: bump js-debug-companion version
811dc8d45a0 Remove authentication provider package.json declaration
8e37e4722ec Fixes #74505 (#117807)
5aeafe2b209 Fix Emmet issue where incorrect abbreviation is displayed in an html document (#117759)
b3ade044793 fixes #117924
0c9476a0b6b testing: fix tree not updating if nodes are replaced with same id
f18a3400668 Use method instead of event
c30e2d46b2a Fix emmet update extensions path issue (#117797)
e4a69193d04 Merge pull request #117138 from shskwmt/fix/116822
a13f7ee916b actionBar: home and end should navigate to first and last item respectively
721514f2c1d Merge pull request #117832 from jeanp413/fix-117354
98883cf3b11 remove actionBar.reverse orientation
0bf5569f02c seti: use CONTRIBUTING
c3e2c76f762 add failing, skipped test for https://github.com/microsoft/vscode/issues/117899
edadf1c7194 Implement shouldPersist for all terminals processes
884ed1e3f33 Use initial instead of unset
b803df2435c Fix top shadow issue
3559e47c08d update gulp-tsb
bf894811515 Some Ports view clean up
73112daff11 Remove extra check that is not needed
e9166375289 tests - enable color output for integration tests
32b3afadcbe support to make N outline entries from 1 cell, https://github.com/microsoft/vscode/issues/115200
85588252af1 notebook - make outline entries use the heading text has preview text
b139c10f9a8 add tests for notebook outline
de020f04d13 debt - make withTestNotebook easier to use
a04913af757 Merge pull request #117716 from microsoft/tyriar/115396
d5eeb40b557 better focus for select boxes in action bars
a2bacaf9fc3 Reverting the top margin to avoid a regression
e4e9d1f43b2 Fix grammar
1c4daf4886c Merge pull request #117842 from TranquilMarmot/main
6a864f0b679 Add line height for title
ba83910eb76 Remove duplicate tooltip
8baa0ebc750 Fixes title casing
36b0a209a51 backups - consolidate web and desktop strategy for backups when auto save is on
b44cc868901 Revisit loose primary group check , use string instead of isPrimaryCheck
12675b4797e missing await
19aee3b6ddf untitled.hint let's go back to the button as the default
6dc076b5c4d debt - tackle an old todo
aacafc75b37 debt - use CompletionItem#textLabel in more places
f5153bbdacd use CompletionItem#textLabel
3c62a8f898b tabs - track last tab in row for wrapping
de50318b48f text files - open an editor that fails to auto save (#115840)
b497d17fec9 View: Maximize editor group" doesnt work with dragged file between editors (fix #117686)
3aff1320b81 my work for march
b99df4f2b6e don't pass model service to applyEdit but check model version for edit that come from extensions, fixes https://github.com/microsoft/vscode/issues/117683
8fd4a68845f Factor in workspace trust when switching versions (#117774)
f84aa806e45 🆙 distro
23dca79e8e9 🆙 nsfwatcher (#117871)
0a7ea106e6e Merge remote-tracking branch 'bpasero/ben/march-debt'
f3ec084d542 Update seti-ui icon theme
b061ac534cb Fix #117833
f3f4eebecbd Label custom editor as deleted if the backing file is deleted
64db4d5a1a5 Fixes #117354
d89e2e17a5d Allow single line comment after `{` for auto indent
5766526b0b3 Port the desktop iframe webivew focus improvements to the web
8572664c6c7 Enable semantic features (such as error reporting) in JS/TS notebook cells
a74ebb17cfe Add helper for tracking active js/ts editor
1f567e10f37 Fixing two more cases for promises in conditionals
3feb2ece1ed Pick up latest TS version for building VS Code
5c7c41fc3d2 Merge pull request #117723 from microsoft/rebornix/reduce-markdown-flickering
91d73da5e42 Only show `infer return type` refactoring when refactorings are requested
d596c568451 fix altClickMovesCursor setting description -> markdownDescription (#117793)
a4187782439 Merge remote-tracking branch 'origin/main' into tyriar/remove_flow_control
d0a46a03279 Merge pull request #117734 from jeanp413/fix-117682
ba9c72b1ff7 Merge pull request #117762 from microsoft/tyriar/remove_ext_host_proc
cadb56785ab Merge branch 'main' into tyriar/remove_ext_host_proc
e0b4ebc148d Merge remote-tracking branch 'origin/main' into tyriar/remove_flow_control
f4c1da9ca64 Update distro
ce4bbc7a19e bump version to 1.55
abdf5767046 ipc - allow to configure proxy
c41922bf427 chore - cleanup registerSingleton service usages
91a246998c2 Remove flow control setting
bd272ea6b74 chore - have a single display change listener
1f0f03e4a03 ipc - adopt utility methods (#114418)
df5d7c257df Remove exthost terminal processes
5f234672f57 fix: only use the readonly attribute on the IOS
509cd79dbd6 text file model - drop custom touch method and just go through normal save code
437904db063 file service - add a atomic read option
45f5c4d43f0 Fixes #117682
3d988a6800f Remove focus handling on the xterm element
9a9551b89fc pfs  - copy should preserve dangling symbolic links
1e799f5a17e anything quick pick - only restore editor view state in certain cases
acea3970993 workspaces - use recursive mkdirSync
a469f5eafaa storage - rename storageservice2 => storageservice
2ab5a60c0b8 storage - drop old node based storage service
5fabc0d9dc1 smoke test - remove code only needed for stable january release
f5d9bdc8466 fix microsoft/vscode#117095 de-duplicate location results
4cda94b60c1 Remove escaping whitespace characters
495c0e996ad fix cursor position when at the start of RTL syntax tokens
234c7a45fee refactor change to fix fault and reduce diff
bf426c250ec structure FilterOptions.textFilter to hold negate flag
03ad36a18b6 Fix negation logic for filterResourceMarkers and filterRelatedInformation
878b0087e06 simplify negate logic in filterMarker
5a6c46fe60a fix #62531 support negation in text filter of Problems
490d7e38da9 Merge branch 'master' into fix-95671
057a47c1b62 Merge branch 'master' into fix-95671
8b73103dedf Merge branch 'master' of https://github.com/matthew-haines/vscode
ac89d9ef71f Fixed logic for setCollapseStateForRest and alt-click in editor
9e1b929816d Fixed logic for setCollapseStateForRest
330f6052ebb Added actions for folding/unfolding all regions except selected
8ef113d399c Added collapse surrounding regions with alt-click
3374969a2cb Fixes #95671
REVERT: fd6f3bce670 chore: bump electron@11.3.0 (#118680)
REVERT: 305bf142199 Remove icon from input row in ports view (#118649)
REVERT: b5af426d34c Properly dispose everything in tunnel view cells (#118546)
REVERT: f299ec03c2a Fix extra port icon (#118529)
REVERT: 62dbffbfe91 Merge pull request #118177 from microsoft/joh/bump-version
REVERT: 062c67a3210 Merge pull request #118491 from microsoft/env-var-recovery
REVERT: e11b6a730c9 Fix #117903 (#118492)
REVERT: e7936a3e885 prevent env var relaunch from extension owned terminals
REVERT: 3be37a725d6 Merge pull request #118438 from microsoft/tyriar/1_54_117990
REVERT: d461d2fd311 Merge pull request #118265 from microsoft/connor4312/candidate/js-debug-1.54.5
REVERT: 88b4d3f9a4e Merge pull request #118448 from microsoft/tyriar/1_54_118321
REVERT: c48a57b6988 Merge pull request #118437 from microsoft/tyriar/1_54_117956
REVERT: d68ab8fc717 Don't force create a terminal on no reconnect
REVERT: f9e6b352d1c Recover on pty host reconnect
REVERT: b31f6e1afea Don't force kill ptys on Windows on window exit
REVERT: bd655647d79 fixes #118214 (#118425)
REVERT: 3a6b7f7cbdc editors - fix mergeAllGroups (#118268) (#118406)
REVERT: 06c5e24837e FileSystemProvider extension: throwing a FileSystemError in readFile does not report to user (#118173)
REVERT: 61feeef2289 Renaming a folder adds it to history (fix #118080) (#118174)
REVERT: dd74fb1d885 debug: update js-debug
REVERT: 362f7e441ff Pick up TS 4.2.3 (#118261)
REVERT: 6b7199812b4 Don't assume uncompleted category exists (#118250)
REVERT: 21ea885f455 Merge pull request #118167 from microsoft/connor4312/candidate/js-debug-1.54.4
REVERT: de16aa4bae0 bump version to future 1.54.2
REVERT: 87ff6fb52f1 debug: update js-debug
REVERT: f30a9b73e8f bump version (#118144)
REVERT: a25525922cd update distro (#118129)
REVERT: 42e27fe5cdc Merge pull request #117982 from microsoft/roblou/settingsOpenEditor
REVERT: ac575425edc Ensure EditorOptions subclass is passed to openEditor Fix #117952
REVERT: 911868fa126 refs #117960 (#117976)
REVERT: 62c69b32bf7 Merge pull request #117972 from microsoft/tyriar/r_1_54_remote_reconnect
REVERT: 564f3917935 Fix remote terminal reconnect
REVERT: e7989863202 fixes #117924 (#117925)
REVERT: c4d7a739c9b Terminal cannot input (#117915)
REVERT: 5266d3cc7f3 Merge pull request #117898 from microsoft/tyriar/r1_54_remote_reconnect
REVERT: 6f0e457db3f Fix emmet update extensions path issue (#117797)
REVERT: 66c7b551727 Implement shouldPersist for all terminals processes
REVERT: ae03e39735b Only show `infer return type` refactoring when refactorings are requested (#117800)

git-subtree-dir: lib/vscode
git-subtree-split: ead2c2ab0f5c93b11e223fd8f4493939be2ee0de
This commit is contained in:
Akash Satheesan
2021-04-09 11:32:26 +05:30
parent e8cd17a97d
commit 801aed9320
1102 changed files with 39897 additions and 23872 deletions

View File

@@ -49,7 +49,11 @@ require('./bootstrap-amd').load(process.env['VSCODE_AMD_ENTRYPOINT']);
function pipeLoggingToParent() {
const MAX_LENGTH = 100000;
// Prevent circular stringify and convert arguments to real array
/**
* Prevent circular stringify and convert arguments to real array
*
* @param {IArguments} args
*/
function safeToArray(args) {
const seen = [];
const argsArray = [];

36
src/bootstrap-node.js vendored
View File

@@ -6,6 +6,42 @@
//@ts-check
'use strict';
// Setup current working directory in all our node & electron processes
// - Windows: call `process.chdir()` to always set application folder as cwd
// - Posix: allow to change the current working dir via `VSCODE_CWD` if defined
// - all OS: store the `process.cwd()` inside `VSCODE_CWD` for consistent lookups
// TODO@bpasero revisit if chdir() on Windows is needed in the future still
function setupCurrentWorkingDirectory() {
const path = require('path');
try {
let cwd = process.env['VSCODE_CWD'];
// remember current working directory in environment
// unless it was given to us already from outside
if (typeof cwd !== 'string') {
cwd = process.cwd();
process.env['VSCODE_CWD'] = cwd;
}
// Windows: always set application folder as current working dir
if (process.platform === 'win32') {
process.chdir(path.dirname(process.execPath));
}
// Linux/macOS: allow to change current working dir based on env
else {
if (cwd !== process.cwd()) {
process.chdir(cwd);
}
}
} catch (err) {
console.error(err);
}
}
setupCurrentWorkingDirectory();
/**
* Add support for redirecting the loading of node modules
*

View File

@@ -23,11 +23,10 @@
}(this, function () {
const bootstrapLib = bootstrap();
const preloadGlobals = globals();
const sandbox = preloadGlobals.context.sandbox;
const webFrame = preloadGlobals.webFrame;
const safeProcess = preloadGlobals.process;
const configuration = parseWindowConfiguration();
const useCustomProtocol = sandbox || typeof safeProcess.env['ENABLE_VSCODE_BROWSER_CODE_LOADING'] === 'string';
const useCustomProtocol = safeProcess.sandboxed || typeof safeProcess.env['ENABLE_VSCODE_BROWSER_CODE_LOADING'] === 'string';
// Start to resolve process.env before anything gets load
// so that we can run loading and resolving in parallel
@@ -83,7 +82,7 @@
}
// replace the patched electron fs with the original node fs for all AMD code (TODO@sandbox non-sandboxed only)
if (!sandbox) {
if (!safeProcess.sandboxed) {
require.define('fs', [], function () { return require.__$__nodeRequire('original-fs'); });
}
@@ -115,7 +114,7 @@
// - sandbox: we list paths of webpacked modules to help the loader
// - non-sandbox: we signal that any module that does not begin with
// `vs/` should be loaded using node.js require()
if (sandbox) {
if (safeProcess.sandboxed) {
loaderConfig.paths = {
'vscode-textmate': `../node_modules/vscode-textmate/release/main`,
'vscode-oniguruma': `../node_modules/vscode-oniguruma/release/main`,
@@ -159,7 +158,9 @@
// Wait for process environment being fully resolved
performance.mark('code/willWaitForShellEnv');
await whenEnvResolved;
if (!safeProcess.env['VSCODE_SKIP_PROCESS_ENV_PATCHING'] /* TODO@bpasero for https://github.com/microsoft/vscode/issues/108804 */) {
await whenEnvResolved;
}
performance.mark('code/didWaitForShellEnv');
// Callback only after process environment is resolved

2
src/bootstrap.js vendored
View File

@@ -180,7 +180,7 @@
}
/**
* @returns {import('./vs/base/parts/sandbox/electron-sandbox/globals').IPartialNodeProcess | NodeJS.Process}
* @returns {import('./vs/base/parts/sandbox/electron-sandbox/globals').ISandboxNodeProcess | NodeJS.Process}
*/
function safeProcess() {
if (typeof process !== 'undefined') {

View File

@@ -15,7 +15,7 @@ const os = require('os');
const { getNLSConfiguration } = require('./vs/base/node/languagePacks');
const bootstrap = require('./bootstrap');
const bootstrapNode = require('./bootstrap-node');
const { getDefaultUserDataPath } = require('./vs/base/node/userDataPath');
const { getUserDataPath } = require('./vs/platform/environment/node/userDataPath');
/** @type {Partial<import('./vs/platform/product/common/productService').IProductConfiguration>} */
const product = require('../product.json');
const { app, protocol, crashReporter } = require('electron');
@@ -49,9 +49,6 @@ if (portable && portable.isPortable) {
app.setAppLogsPath(path.join(userDataPath, 'logs'));
}
// Update cwd based on environment and platform
setCurrentWorkingDirectory();
// Register custom schemes with privileges
protocol.registerSchemesAsPrivileged([
{
@@ -161,9 +158,12 @@ function configureCommandlineSwitchesSync(cliArgs) {
// Persistently enable proposed api via argv.json: https://github.com/microsoft/vscode/issues/99775
'enable-proposed-api',
// TODO@bpasero remove me once testing is done on `vscode-file` protocol
// TODO@sandbox remove me once testing is done on `vscode-file` protocol
// (all traces of `enable-browser-code-loading` and `ENABLE_VSCODE_BROWSER_CODE_LOADING`)
'enable-browser-code-loading'
'enable-browser-code-loading',
// Log level to use. Default is 'info'. Allowed values are 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.
'log-level',
];
// Read argv config
@@ -208,6 +208,12 @@ function configureCommandlineSwitchesSync(cliArgs) {
process.env['ENABLE_VSCODE_BROWSER_CODE_LOADING'] = argvValue;
}
break;
case 'log-level':
if (typeof argvValue === 'string') {
process.argv.push('--log', argvValue);
}
break;
}
}
});
@@ -424,19 +430,6 @@ function getJSFlags(cliArgs) {
return jsFlags.length > 0 ? jsFlags.join(' ') : null;
}
/**
* @param {import('./vs/platform/environment/common/argv').NativeParsedArgs} cliArgs
*
* @returns {string}
*/
function getUserDataPath(cliArgs) {
if (portable.isPortable) {
return path.join(portable.portableDataPath, 'user-data');
}
return path.resolve(cliArgs['user-data-dir'] || getDefaultUserDataPath());
}
/**
* @returns {import('./vs/platform/environment/common/argv').NativeParsedArgs}
*/
@@ -454,19 +447,6 @@ function parseCLIArgs() {
});
}
function setCurrentWorkingDirectory() {
try {
if (process.platform === 'win32') {
process.env['VSCODE_CWD'] = process.cwd(); // remember as environment variable
process.chdir(path.dirname(app.getPath('exe'))); // always set application folder as cwd
} else if (process.env['VSCODE_CWD']) {
process.chdir(process.env['VSCODE_CWD']);
}
} catch (err) {
console.error(err);
}
}
function registerListeners() {
/**
@@ -516,7 +496,7 @@ function getNodeCachedDir() {
return new class {
constructor() {
this.value = this._compute();
this.value = this.compute();
}
async ensureExists() {
@@ -531,7 +511,7 @@ function getNodeCachedDir() {
}
}
_compute() {
compute() {
if (process.argv.indexOf('--no-cached-data') > 0) {
return undefined;
}

View File

@@ -1,9 +1,13 @@
{
"ban-eval-calls": [
"vs/workbench/api/worker/extHostExtensionService.ts"
"vs/workbench/api/worker/extHostExtensionService.ts",
"vs/base/worker/workerMain",
"vs/workbench/services/extensions/worker/extensionHostWorkerMain"
],
"ban-function-calls": [
"vs/workbench/api/worker/extHostExtensionService.ts",
"vs/base/worker/workerMain",
"vs/workbench/services/extensions/worker/extensionHostWorkerMain",
"vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts",
"vs/workbench/services/keybinding/test/electron-browser/keyboardMapperTestUtils.ts"
],

View File

@@ -383,6 +383,7 @@ export class SelectActionViewItem extends BaseActionViewItem {
super(ctx, action);
this.selectBox = new SelectBox(options, selected, contextViewProvider, undefined, selectBoxOptions);
this.selectBox.setFocusable(false);
this._register(this.selectBox);
this.registerListeners();
@@ -406,6 +407,10 @@ export class SelectActionViewItem extends BaseActionViewItem {
return option;
}
setFocusable(focusable: boolean): void {
this.selectBox.setFocusable(focusable);
}
focus(): void {
if (this.selectBox) {
this.selectBox.focus();

View File

@@ -20,10 +20,6 @@
display: inline-block;
}
.monaco-action-bar.reverse .actions-container {
flex-direction: row-reverse;
}
.monaco-action-bar .action-item {
cursor: pointer;
display: inline-block;

View File

@@ -28,9 +28,7 @@ export interface IActionViewItemProvider {
export const enum ActionsOrientation {
HORIZONTAL,
HORIZONTAL_REVERSE,
VERTICAL,
VERTICAL_REVERSE,
}
export interface ActionTrigger {
@@ -135,21 +133,11 @@ export class ActionBar extends Disposable implements IActionRunner {
previousKeys = [KeyCode.LeftArrow];
nextKeys = [KeyCode.RightArrow];
break;
case ActionsOrientation.HORIZONTAL_REVERSE:
previousKeys = [KeyCode.RightArrow];
nextKeys = [KeyCode.LeftArrow];
this.domNode.className += ' reverse';
break;
case ActionsOrientation.VERTICAL:
previousKeys = [KeyCode.UpArrow];
nextKeys = [KeyCode.DownArrow];
this.domNode.className += ' vertical';
break;
case ActionsOrientation.VERTICAL_REVERSE:
previousKeys = [KeyCode.DownArrow];
nextKeys = [KeyCode.UpArrow];
this.domNode.className += ' vertical reverse';
break;
}
this._register(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_DOWN, e => {
@@ -163,8 +151,12 @@ export class ActionBar extends Disposable implements IActionRunner {
eventHandled = this.focusNext();
} else if (event.equals(KeyCode.Escape) && this.cancelHasListener) {
this._onDidCancel.fire();
} else if (event.equals(KeyCode.Home)) {
eventHandled = this.focusFirst();
} else if (event.equals(KeyCode.End)) {
eventHandled = this.focusLast();
} else if (event.equals(KeyCode.Tab) && focusedItem instanceof BaseActionViewItem && focusedItem.trapsArrowNavigation) {
this.focusNext();
eventHandled = this.focusNext();
} else if (this.isTriggerKeyEvent(event)) {
// Staying out of the else branch even if not triggered
if (this._triggerKeys.keyDown) {
@@ -425,9 +417,21 @@ export class ActionBar extends Disposable implements IActionRunner {
}
}
private focusFirst(): boolean {
this.focusedItem = this.length() > 1 ? 1 : 0;
return this.focusPrevious();
}
private focusLast(): boolean {
this.focusedItem = this.length() < 2 ? 0 : this.length() - 2;
return this.focusNext();
}
protected focusNext(): boolean {
if (typeof this.focusedItem === 'undefined') {
this.focusedItem = this.viewItems.length - 1;
} else if (this.viewItems.length <= 1) {
return false;
}
const startIndex = this.focusedItem;
@@ -450,6 +454,8 @@ export class ActionBar extends Disposable implements IActionRunner {
protected focusPrevious(): boolean {
if (typeof this.focusedItem === 'undefined') {
this.focusedItem = 0;
} else if (this.viewItems.length <= 1) {
return false;
}
const startIndex = this.focusedItem;

View File

@@ -14,6 +14,10 @@
align-items: center;
}
.monaco-text-button:focus {
outline-offset: 2px !important;
}
.monaco-text-button:hover {
text-decoration: none !important;
}

View File

@@ -20,4 +20,5 @@ export interface IHoverDelegateOptions {
export interface IHoverDelegate {
showHover(options: IHoverDelegateOptions): IDisposable | undefined;
delay: number;
}

View File

@@ -10,7 +10,6 @@ import { IMatch } from 'vs/base/common/filters';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { Range } from 'vs/base/common/range';
import { equals } from 'vs/base/common/objects';
import { isMacintosh } from 'vs/base/common/platform';
import { IHoverDelegate, IHoverDelegateOptions, IHoverDelegateTarget } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
import { AnchorPosition } from 'vs/base/browser/ui/contextview/contextview';
import { IMarkdownString } from 'vs/base/common/htmlContent';
@@ -218,9 +217,6 @@ export class IconLabel extends Disposable {
htmlElement.removeAttribute('title');
let tooltip = this.getTooltipForCustom(markdownTooltip);
// Testing has indicated that on Windows and Linux 500 ms matches the native hovers most closely.
// On Mac, the delay is 1500.
const hoverDelay = isMacintosh ? 1500 : 500;
let hoverOptions: IHoverDelegateOptions | undefined;
let mouseX: number | undefined;
let isHovering = false;
@@ -232,9 +228,12 @@ export class IconLabel extends Disposable {
}
tokenSource = new CancellationTokenSource();
function mouseLeaveOrDown(this: HTMLElement, e: MouseEvent): any {
if ((e.type === dom.EventType.MOUSE_DOWN) || (<any>e).fromElement === htmlElement) {
const isMouseDown = e.type === dom.EventType.MOUSE_DOWN;
if (isMouseDown) {
hoverDisposable?.dispose();
hoverDisposable = undefined;
}
if (isMouseDown || (<any>e).fromElement === htmlElement) {
isHovering = false;
hoverOptions = undefined;
tokenSource.dispose(true);
@@ -282,7 +281,7 @@ export class IconLabel extends Disposable {
}
mouseMoveDisposable.dispose();
}, hoverDelay);
}, hoverDelegate.delay);
}
const mouseOverDisposable = this._register(domEvent(htmlElement, dom.EventType.MOUSE_OVER, true)(mouseOver.bind(htmlElement)));
this.customHovers.set(htmlElement, mouseOverDisposable);

View File

@@ -27,6 +27,7 @@ const $ = dom.$;
export interface IInputOptions extends IInputBoxStyles {
readonly placeholder?: string;
readonly tooltip?: string;
readonly ariaLabel?: string;
readonly type?: string;
readonly validationOptions?: IInputValidationOptions;
@@ -95,6 +96,7 @@ export class InputBox extends Widget {
private options: IInputOptions;
private message: IMessage | null;
private placeholder: string;
private tooltip: string;
private ariaLabel: string;
private validation?: IInputValidator;
private state: 'idle' | 'open' | 'closed' = 'idle';
@@ -133,6 +135,7 @@ export class InputBox extends Widget {
mixin(this.options, defaultOpts, false);
this.message = null;
this.placeholder = this.options.placeholder || '';
this.tooltip = this.options.tooltip ?? (this.placeholder || '');
this.ariaLabel = this.options.ariaLabel || '';
this.inputBackground = this.options.inputBackground;
@@ -207,6 +210,10 @@ export class InputBox extends Widget {
this.setPlaceHolder(this.placeholder);
}
if (this.tooltip) {
this.setTooltip(this.tooltip);
}
this.oninput(this.input, () => this.onValueChange());
this.onblur(this.input, () => this.onBlur());
this.onfocus(this.input, () => this.onFocus());
@@ -235,7 +242,11 @@ export class InputBox extends Widget {
public setPlaceHolder(placeHolder: string): void {
this.placeholder = placeHolder;
this.input.setAttribute('placeholder', placeHolder);
this.input.title = placeHolder;
}
public setTooltip(tooltip: string): void {
this.tooltip = tooltip;
this.input.title = tooltip;
}
public setAriaLabel(label: string): void {

View File

@@ -226,6 +226,14 @@ export class PagedList<T> implements IThemable, IDisposable {
this.list.scrollLeft = scrollLeft;
}
setAnchor(index: number | undefined): void {
this.list.setAnchor(index);
}
getAnchor(): number | undefined {
return this.list.getAnchor();
}
setFocus(indexes: number[]): void {
this.list.setFocus(indexes);
}
@@ -238,12 +246,20 @@ export class PagedList<T> implements IThemable, IDisposable {
this.list.focusPrevious(n, loop);
}
focusNextPage(): void {
this.list.focusNextPage();
focusNextPage(): Promise<void> {
return this.list.focusNextPage();
}
focusPreviousPage(): void {
this.list.focusPreviousPage();
focusPreviousPage(): Promise<void> {
return this.list.focusPreviousPage();
}
focusLast(): void {
this.list.focusLast();
}
focusFirst(): void {
this.list.focusFirst();
}
getFocus(): number[] {

View File

@@ -6,7 +6,7 @@
import 'vs/css!./list';
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { isNumber } from 'vs/base/common/types';
import { range, binarySearch } from 'vs/base/common/arrays';
import { range, binarySearch, firstOrDefault } from 'vs/base/common/arrays';
import { memoize } from 'vs/base/common/decorators';
import * as platform from 'vs/base/common/platform';
import { Gesture } from 'vs/base/browser/touch';
@@ -27,6 +27,7 @@ import { IDragAndDropData } from 'vs/base/browser/dnd';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { IThemable } from 'vs/base/common/styler';
import { createStyleSheet } from 'vs/base/browser/dom';
import { timeout } from 'vs/base/common/async';
interface ITraitChangeEvent {
indexes: number[];
@@ -617,27 +618,25 @@ export class MouseController<T> implements IDisposable {
return;
}
let reference = this.list.getFocus()[0];
const selection = this.list.getSelection();
reference = reference === undefined ? selection[0] : reference;
const focus = e.index;
if (typeof focus === 'undefined') {
this.list.setFocus([], e.browserEvent);
this.list.setSelection([], e.browserEvent);
this.list.setAnchor(undefined);
return;
}
if (this.multipleSelectionSupport && this.isSelectionRangeChangeEvent(e)) {
return this.changeSelection(e, reference);
return this.changeSelection(e);
}
if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) {
return this.changeSelection(e, reference);
return this.changeSelection(e);
}
this.list.setFocus([focus], e.browserEvent);
this.list.setAnchor(focus);
if (!isMouseRightClick(e.browserEvent)) {
this.list.setSelection([focus], e.browserEvent);
@@ -659,15 +658,16 @@ export class MouseController<T> implements IDisposable {
this.list.setSelection(focus, e.browserEvent);
}
private changeSelection(e: IListMouseEvent<T> | IListTouchEvent<T>, reference: number | undefined): void {
private changeSelection(e: IListMouseEvent<T> | IListTouchEvent<T>): void {
const focus = e.index!;
const anchor = this.list.getAnchor();
if (this.isSelectionRangeChangeEvent(e) && reference !== undefined) {
const min = Math.min(reference, focus);
const max = Math.max(reference, focus);
if (this.isSelectionRangeChangeEvent(e) && typeof anchor === 'number') {
const min = Math.min(anchor, focus);
const max = Math.max(anchor, focus);
const rangeSelection = range(min, max + 1);
const selection = this.list.getSelection();
const contiguousRange = getContiguousRangeContaining(disjunction(selection, [reference]), reference);
const contiguousRange = getContiguousRangeContaining(disjunction(selection, [anchor]), anchor);
if (contiguousRange.length === 0) {
return;
@@ -675,12 +675,14 @@ export class MouseController<T> implements IDisposable {
const newSelection = disjunction(rangeSelection, relativeComplement(selection, contiguousRange));
this.list.setSelection(newSelection, e.browserEvent);
this.list.setFocus([focus], e.browserEvent);
} else if (this.isSelectionSingleChangeEvent(e)) {
const selection = this.list.getSelection();
const newSelection = selection.filter(i => i !== focus);
this.list.setFocus([focus]);
this.list.setAnchor(focus);
if (selection.length === newSelection.length) {
this.list.setSelection([...newSelection, focus], e.browserEvent);
@@ -1130,8 +1132,9 @@ export interface IListOptionsUpdate extends IListViewOptionsUpdate {
export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
private focus: Trait<T>;
private focus = new Trait<T>('focused');
private selection: Trait<T>;
private anchor = new Trait<T>('anchor');
private eventBufferer = new EventBufferer();
protected view: ListView<T>;
private spliceable: ISpliceable<T>;
@@ -1223,7 +1226,6 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
) {
const role = this._options.accessibilityProvider && this._options.accessibilityProvider.getWidgetRole ? this._options.accessibilityProvider?.getWidgetRole() : 'list';
this.selection = new SelectionTrait(role !== 'listbox');
this.focus = new Trait('focused');
mixin(_options, defaultStyles, false);
@@ -1259,11 +1261,13 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
this.spliceable = new CombinedSpliceable([
new TraitSpliceable(this.focus, this.view, _options.identityProvider),
new TraitSpliceable(this.selection, this.view, _options.identityProvider),
new TraitSpliceable(this.anchor, this.view, _options.identityProvider),
this.view
]);
this.disposables.add(this.focus);
this.disposables.add(this.selection);
this.disposables.add(this.anchor);
this.disposables.add(this.view);
this.disposables.add(this._onDidDispose);
@@ -1436,6 +1440,23 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
return this.getSelection().map(i => this.view.element(i));
}
setAnchor(index: number | undefined): void {
if (typeof index === 'undefined') {
this.anchor.set([]);
return;
}
if (index < 0 || index >= this.length) {
throw new ListError(this.user, `Invalid index ${index}`);
}
this.anchor.set([index]);
}
getAnchor(): number | undefined {
return firstOrDefault(this.anchor.get(), undefined);
}
setFocus(indexes: number[], browserEvent?: UIEvent): void {
for (const index of indexes) {
if (index < 0 || index >= this.length) {
@@ -1468,7 +1489,7 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
}
}
focusNextPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): void {
async focusNextPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): Promise<void> {
let lastPageIndex = this.view.indexAt(this.view.getScrollTop() + this.view.renderHeight);
lastPageIndex = lastPageIndex === 0 ? 0 : lastPageIndex - 1;
const lastPageElement = this.view.element(lastPageIndex);
@@ -1490,12 +1511,13 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
this.setFocus([]);
// Let the scroll event listener run
setTimeout(() => this.focusNextPage(browserEvent, filter), 0);
await timeout(0);
await this.focusNextPage(browserEvent, filter);
}
}
}
focusPreviousPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): void {
async focusPreviousPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): Promise<void> {
let firstPageIndex: number;
const scrollTop = this.view.getScrollTop();
@@ -1524,7 +1546,8 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
this.setFocus([]);
// Let the scroll event listener run
setTimeout(() => this.focusPreviousPage(browserEvent, filter), 0);
await timeout(0);
await this.focusPreviousPage(browserEvent, filter);
}
}
}

View File

@@ -85,3 +85,11 @@
.menubar.compact .toolbar-toggle-more::before {
content: "\eb94" !important;
}
/* Match behavior of outline for activity bar icons */
.menubar.compact > .menubar-menu-button.open,
.menubar.compact > .menubar-menu-button:focus,
.menubar.compact > .menubar-menu-button:hover {
outline-width: 1px !important;
outline-offset: -8px !important;
}

View File

@@ -976,7 +976,7 @@ export class MenuBar extends Disposable {
menuHolder.style.right = `${this.container.clientWidth}px`;
menuHolder.style.left = 'auto';
} else {
menuHolder.style.top = `${this.container.clientHeight}px`;
menuHolder.style.top = `${buttonBoundingRect.bottom}px`;
menuHolder.style.left = `${buttonBoundingRect.left}px`;
}

View File

@@ -85,27 +85,42 @@
}
.monaco-sash.vertical > .orthogonal-drag-handle.start {
left: calc(var(--sash-size) / -2);
left: calc(var(--sash-size) * -0.5);
top: calc(var(--sash-size) * -1);
}
.monaco-sash.vertical > .orthogonal-drag-handle.end {
left: calc(var(--sash-size) / -2);
left: calc(var(--sash-size) * -0.5);
bottom: calc(var(--sash-size) * -1);
}
.monaco-sash.horizontal > .orthogonal-drag-handle.start {
top: calc(var(--sash-size) / -2);
top: calc(var(--sash-size) * -0.5);
left: calc(var(--sash-size) * -1);
}
.monaco-sash.horizontal > .orthogonal-drag-handle.end {
top: calc(var(--sash-size) / -2);
top: calc(var(--sash-size) * -0.5);
right: calc(var(--sash-size) * -1);
}
.monaco-sash {
.monaco-sash:before {
content: '';
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
transition: background-color 0.1s ease-out;
background: transparent;
}
.monaco-sash.vertical:before {
width: var(--sash-hover-size);
left: calc(50% - (var(--sash-hover-size) / 2));
}
.monaco-sash.horizontal:before {
height: var(--sash-hover-size);
top: calc(50% - (var(--sash-hover-size) / 2));
}
/** Debug **/
.monaco-sash.debug {

View File

@@ -81,6 +81,13 @@ export function setGlobalSashSize(size: number): void {
onDidChangeGlobalSize.fire(size);
}
let globalHoverDelay = 300;
const onDidChangeHoverDelay = new Emitter<number>();
export function setGlobalHoverDelay(size: number): void {
globalHoverDelay = size;
onDidChangeHoverDelay.fire(size);
}
export class Sash extends Disposable {
private el: HTMLElement;
@@ -88,7 +95,8 @@ export class Sash extends Disposable {
private hidden: boolean;
private orientation!: Orientation;
private size: number;
private hoverDelayer = this._register(new Delayer(300));
private hoverDelay = globalHoverDelay;
private hoverDelayer = this._register(new Delayer(this.hoverDelay));
private _state: SashState = SashState.Enabled;
get state(): SashState { return this._state; }
@@ -221,6 +229,8 @@ export class Sash extends Disposable {
}));
}
this._register(onDidChangeHoverDelay.event(delay => this.hoverDelay = delay));
this.hidden = false;
this.layoutProvider = layoutProvider;
@@ -403,7 +413,7 @@ export class Sash extends Disposable {
sash.hoverDelayer.cancel();
sash.el.classList.add('hover');
} else {
sash.hoverDelayer.trigger(() => sash.el.classList.add('hover'));
sash.hoverDelayer.trigger(() => sash.el.classList.add('hover'), sash.hoverDelay).then(undefined, () => { });
}
if (!fromLinkedSash && sash.linkedSash) {

View File

@@ -29,6 +29,7 @@ export interface ISelectBoxDelegate extends IDisposable {
setAriaLabel(label: string): void;
focus(): void;
blur(): void;
setFocusable(focus: boolean): void;
// Delegated Widget interface
render(container: HTMLElement): void;
@@ -93,41 +94,43 @@ export class SelectBox extends Widget implements ISelectBoxDelegate {
// Public SelectBox Methods - routed through delegate interface
public get onDidSelect(): Event<ISelectData> {
get onDidSelect(): Event<ISelectData> {
return this.selectBoxDelegate.onDidSelect;
}
public setOptions(options: ISelectOptionItem[], selected?: number): void {
setOptions(options: ISelectOptionItem[], selected?: number): void {
this.selectBoxDelegate.setOptions(options, selected);
}
public select(index: number): void {
select(index: number): void {
this.selectBoxDelegate.select(index);
}
public setAriaLabel(label: string): void {
setAriaLabel(label: string): void {
this.selectBoxDelegate.setAriaLabel(label);
}
public focus(): void {
focus(): void {
this.selectBoxDelegate.focus();
}
public blur(): void {
blur(): void {
this.selectBoxDelegate.blur();
}
// Public Widget Methods - routed through delegate interface
setFocusable(focusable: boolean): void {
this.selectBoxDelegate.setFocusable(focusable);
}
public render(container: HTMLElement): void {
render(container: HTMLElement): void {
this.selectBoxDelegate.render(container);
}
public style(styles: ISelectBoxStyles): void {
style(styles: ISelectBoxStyles): void {
this.selectBoxDelegate.style(styles);
}
public applyStyles(): void {
applyStyles(): void {
this.selectBoxDelegate.applyStyles();
}
}

View File

@@ -293,16 +293,22 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
public focus(): void {
if (this.selectElement) {
this.selectElement.tabIndex = 0;
this.selectElement.focus();
}
}
public blur(): void {
if (this.selectElement) {
this.selectElement.tabIndex = -1;
this.selectElement.blur();
}
}
public setFocusable(focusable: boolean): void {
this.selectElement.tabIndex = focusable ? 0 : -1;
}
public render(container: HTMLElement): void {
this.container = container;
container.classList.add('select-container');

View File

@@ -132,16 +132,22 @@ export class SelectBoxNative extends Disposable implements ISelectBoxDelegate {
public focus(): void {
if (this.selectElement) {
this.selectElement.tabIndex = 0;
this.selectElement.focus();
}
}
public blur(): void {
if (this.selectElement) {
this.selectElement.tabIndex = -1;
this.selectElement.blur();
}
}
public setFocusable(focusable: boolean): void {
this.selectElement.tabIndex = focusable ? 0 : -1;
}
public render(container: HTMLElement): void {
container.classList.add('select-container');
container.appendChild(this.selectElement);

View File

@@ -73,6 +73,7 @@
align-items: center;
justify-content: center;
color: inherit;
outline-offset: -2px;
}
.monaco-pane-view .pane > .pane-header .monaco-action-bar .action-item.select-container {

View File

@@ -22,6 +22,7 @@
.monaco-table-tr {
display: flex;
height: 100%;
}
.monaco-table-th {
@@ -35,18 +36,12 @@
.monaco-table-th,
.monaco-table-td {
box-sizing: border-box;
padding-left: 10px;
flex-shrink: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.monaco-table-th[data-col-index="0"],
.monaco-table-td[data-col-index="0"] {
padding-left: 20px;
}
.monaco-table > .monaco-split-view2 .monaco-sash.vertical::before {
content: "";
position: absolute;

View File

@@ -250,7 +250,10 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
this.cachedHeight = height;
this.splitview.layout(width);
this.list.layout(height - this.virtualDelegate.headerRowHeight, width);
const listHeight = height - this.virtualDelegate.headerRowHeight;
this.list.getHTMLElement().style.height = `${listHeight}px`;
this.list.layout(listHeight, width);
}
toggleKeyboardNavigation(): void {
@@ -273,6 +276,14 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
this.list.domFocus();
}
setAnchor(index: number | undefined): void {
this.list.setAnchor(index);
}
getAnchor(): number | undefined {
return this.list.getAnchor();
}
getSelectedElements(): TRow[] {
return this.list.getSelectedElements();
}
@@ -297,12 +308,12 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
this.list.focusPrevious(n, loop, browserEvent);
}
focusNextPage(browserEvent?: UIEvent): void {
this.list.focusNextPage(browserEvent);
focusNextPage(browserEvent?: UIEvent): Promise<void> {
return this.list.focusNextPage(browserEvent);
}
focusPreviousPage(browserEvent?: UIEvent): void {
this.list.focusPreviousPage(browserEvent);
focusPreviousPage(browserEvent?: UIEvent): Promise<void> {
return this.list.focusPreviousPage(browserEvent);
}
focusFirst(browserEvent?: UIEvent): void {
@@ -317,6 +328,10 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
return this.list.getFocus();
}
getFocusedElements(): TRow[] {
return this.list.getFocusedElements();
}
reveal(index: number, relativeTop?: number): void {
this.list.reveal(index, relativeTop);
}

View File

@@ -14,7 +14,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
import { ITreeModel, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeFilter, ITreeNavigator, ICollapseStateChangeEvent, ITreeDragAndDrop, TreeDragOverBubble, TreeVisibility, TreeFilterResult, ITreeModelSpliceEvent, TreeMouseEventTarget } from 'vs/base/browser/ui/tree/tree';
import { ISpliceable } from 'vs/base/common/sequence';
import { IDragAndDropData, StaticDND, DragAndDropData } from 'vs/base/browser/dnd';
import { range, equals, distinctES6 } from 'vs/base/common/arrays';
import { range, equals, distinctES6, firstOrDefault } from 'vs/base/common/arrays';
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { domEvent } from 'vs/base/browser/event';
import { fuzzyScore, FuzzyScore } from 'vs/base/common/filters';
@@ -683,6 +683,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
if (typeof options.filterOnType !== 'undefined') {
this._filterOnType = !!options.filterOnType;
this.filterOnTypeDomNode.checked = this._filterOnType;
this.updateFilterOnTypeTitleAndIcon();
}
if (typeof options.automaticKeyboardNavigation !== 'undefined') {
@@ -1168,6 +1169,7 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
renderers: IListRenderer<any /* TODO@joao */, any>[],
private focusTrait: Trait<T>,
private selectionTrait: Trait<T>,
private anchorTrait: Trait<T>,
options: ITreeNodeListOptions<T, TFilterData, TRef>
) {
super(user, container, virtualDelegate, renderers, options);
@@ -1186,6 +1188,7 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
const additionalFocus: number[] = [];
const additionalSelection: number[] = [];
let anchor: number | undefined;
elements.forEach((node, index) => {
if (this.focusTrait.has(node)) {
@@ -1195,6 +1198,10 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
if (this.selectionTrait.has(node)) {
additionalSelection.push(start + index);
}
if (this.anchorTrait.has(node)) {
anchor = start + index;
}
});
if (additionalFocus.length > 0) {
@@ -1204,6 +1211,10 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
if (additionalSelection.length > 0) {
super.setSelection(distinctES6([...super.getSelection(), ...additionalSelection]));
}
if (typeof anchor === 'number') {
super.setAnchor(anchor);
}
}
setFocus(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void {
@@ -1221,6 +1232,18 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
this.selectionTrait.set(indexes.map(i => this.element(i)), browserEvent);
}
}
setAnchor(index: number | undefined, fromAPI = false): void {
super.setAnchor(index);
if (!fromAPI) {
if (typeof index === 'undefined') {
this.anchorTrait.set([]);
} else {
this.anchorTrait.set([this.element(index)]);
}
}
}
}
export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable {
@@ -1230,6 +1253,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
protected model: ITreeModel<T, TFilterData, TRef>;
private focus: Trait<T>;
private selection: Trait<T>;
private anchor: Trait<T>;
private eventBufferer = new EventBufferer();
private typeFilterController?: TypeFilterController<T, TFilterData>;
private focusNavigationFilter: ((node: ITreeNode<T, TFilterData>) => boolean) | undefined;
@@ -1298,7 +1322,8 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
this.focus = new Trait(_options.identityProvider);
this.selection = new Trait(_options.identityProvider);
this.view = new TreeNodeList(user, container, treeDelegate, this.renderers, this.focus, this.selection, { ...asListOptions(() => this.model, _options), tree: this });
this.anchor = new Trait(_options.identityProvider);
this.view = new TreeNodeList(user, container, treeDelegate, this.renderers, this.focus, this.selection, this.anchor, { ...asListOptions(() => this.model, _options), tree: this });
this.model = this.createModel(user, this.view, _options);
onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState;
@@ -1552,6 +1577,25 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
this.model.refilter();
}
setAnchor(element: TRef | undefined): void {
if (typeof element === 'undefined') {
return this.view.setAnchor(undefined);
}
const node = this.model.getNode(element);
this.anchor.set([node]);
const index = this.model.getListIndex(element);
if (index > -1) {
this.view.setAnchor(index, true);
}
}
getAnchor(): T | undefined {
return firstOrDefault(this.anchor.get(), undefined);
}
setSelection(elements: TRef[], browserEvent?: UIEvent): void {
const nodes = elements.map(e => this.model.getNode(e));
this.selection.set(nodes, browserEvent);
@@ -1580,12 +1624,12 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
this.view.focusPrevious(n, loop, browserEvent, filter);
}
focusNextPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void {
this.view.focusNextPage(browserEvent, filter);
focusNextPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): Promise<void> {
return this.view.focusNextPage(browserEvent, filter);
}
focusPreviousPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void {
this.view.focusPreviousPage(browserEvent, filter);
focusPreviousPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): Promise<void> {
return this.view.focusPreviousPage(browserEvent, filter);
}
focusLast(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void {

View File

@@ -616,7 +616,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return this.tree.isCollapsible(this.getDataNode(element));
}
isCollapsed(element: T): boolean {
isCollapsed(element: TInput | T): boolean {
return this.tree.isCollapsed(this.getDataNode(element));
}
@@ -628,6 +628,15 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
this.tree.refilter();
}
setAnchor(element: T | undefined): void {
this.tree.setAnchor(typeof element === 'undefined' ? undefined : this.getDataNode(element));
}
getAnchor(): T | undefined {
const node = this.tree.getAnchor();
return node?.element as T;
}
setSelection(elements: T[], browserEvent?: UIEvent): void {
const nodes = elements.map(e => this.getDataNode(e));
this.tree.setSelection(nodes, browserEvent);
@@ -651,12 +660,12 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
this.tree.focusPrevious(n, loop, browserEvent);
}
focusNextPage(browserEvent?: UIEvent): void {
this.tree.focusNextPage(browserEvent);
focusNextPage(browserEvent?: UIEvent): Promise<void> {
return this.tree.focusNextPage(browserEvent);
}
focusPreviousPage(browserEvent?: UIEvent): void {
this.tree.focusPreviousPage(browserEvent);
focusPreviousPage(browserEvent?: UIEvent): Promise<void> {
return this.tree.focusPreviousPage(browserEvent);
}
focusLast(browserEvent?: UIEvent): void {

View File

@@ -8,7 +8,6 @@ import { IndexTreeModel, IIndexTreeModelOptions, IList, IIndexTreeModelSpliceOpt
import { Event } from 'vs/base/common/event';
import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter, ICollapseStateChangeEvent, ITreeModelSpliceEvent, TreeError } from 'vs/base/browser/ui/tree/tree';
import { IIdentityProvider } from 'vs/base/browser/ui/list/list';
import { mergeSort } from 'vs/base/common/arrays';
export type ITreeNodeCallback<T, TFilterData> = (node: ITreeNode<T, TFilterData>) => void;
@@ -130,7 +129,7 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
private preserveCollapseState(elements: Iterable<ITreeElement<T>> = Iterable.empty()): Iterable<ITreeElement<T>> {
if (this.sorter) {
elements = mergeSort([...elements], this.sorter.compare.bind(this.sorter));
elements = [...elements].sort(this.sorter.compare.bind(this.sorter));
}
return Iterable.map(elements, treeElement => {
@@ -185,7 +184,7 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
let childrenNodes = [...node.children] as ITreeNode<T, TFilterData>[];
if (recursive || first) {
childrenNodes = mergeSort(childrenNodes, this.sorter!.compare.bind(this.sorter));
childrenNodes = childrenNodes.sort(this.sorter!.compare.bind(this.sorter));
}
return Iterable.map<ITreeNode<T | null, TFilterData>, ITreeElement<T>>(childrenNodes, node => ({

View File

@@ -3,23 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { mergeSort } from 'vs/base/common/arrays';
import { URI } from 'vs/base/common/uri';
/**
* @deprecated use `FileAccess.asFileUri(relativePath, requireFn).fsPath`
*/
export function getPathFromAmdModule(requirefn: typeof require, relativePath: string): string {
return getUriFromAmdModule(requirefn, relativePath).fsPath;
}
/**
* @deprecated use `FileAccess.asFileUri()` for node.js contexts or `FileAccess.asBrowserUri` for browser contexts.
*/
export function getUriFromAmdModule(requirefn: typeof require, relativePath: string): URI {
return URI.parse(requirefn.toUrl(relativePath));
}
export abstract class LoaderStats {
abstract get amdLoad(): [string, number][];
abstract get amdInvoke(): [string, number][];
@@ -27,10 +10,7 @@ export abstract class LoaderStats {
abstract get nodeEval(): [string, number][];
abstract get nodeRequireTotal(): number;
static get(): LoaderStats {
const amdLoadScript = new Map<string, number>();
const amdInvokeFactory = new Map<string, number>();
const nodeRequire = new Map<string, number>();
@@ -60,7 +40,7 @@ export abstract class LoaderStats {
map.set(stat.detail, duration + stat.timestamp);
}
const stats = mergeSort(require.getStats().slice(0), (a, b) => a.timestamp - b.timestamp);
const stats = require.getStats().slice(0).sort((a, b) => a.timestamp - b.timestamp);
for (const stat of stats) {
switch (stat.type) {

View File

@@ -121,58 +121,10 @@ export function quickSelect<T>(nth: number, data: T[], compare: Compare<T>): T {
}
}
/**
* Like `Array#sort` but always stable. Usually runs a little slower `than Array#sort`
* so only use this when actually needing stable sort.
*/
export function mergeSort<T>(data: T[], compare: Compare<T>): T[] {
_sort(data, compare, 0, data.length - 1, []);
return data;
}
function _merge<T>(a: T[], compare: Compare<T>, lo: number, mid: number, hi: number, aux: T[]): void {
let leftIdx = lo, rightIdx = mid + 1;
for (let i = lo; i <= hi; i++) {
aux[i] = a[i];
}
for (let i = lo; i <= hi; i++) {
if (leftIdx > mid) {
// left side consumed
a[i] = aux[rightIdx++];
} else if (rightIdx > hi) {
// right side consumed
a[i] = aux[leftIdx++];
} else if (compare(aux[rightIdx], aux[leftIdx]) < 0) {
// right element is less -> comes first
a[i] = aux[rightIdx++];
} else {
// left element comes first (less or equal)
a[i] = aux[leftIdx++];
}
}
}
function _sort<T>(a: T[], compare: Compare<T>, lo: number, hi: number, aux: T[]) {
if (hi <= lo) {
return;
}
const mid = lo + ((hi - lo) / 2) | 0;
_sort(a, compare, lo, mid, aux);
_sort(a, compare, mid + 1, hi, aux);
if (compare(a[mid], a[mid + 1]) <= 0) {
// left and right are sorted and if the last-left element is less
// or equals than the first-right element there is nothing else
// to do
return;
}
_merge(a, compare, lo, mid, hi, aux);
}
export function groupBy<T>(data: ReadonlyArray<T>, compare: (a: T, b: T) => number): T[][] {
const result: T[][] = [];
let currentGroup: T[] | undefined = undefined;
for (const element of mergeSort(data.slice(0), compare)) {
for (const element of data.slice(0).sort(compare)) {
if (!currentGroup || compare(currentGroup[0], element) !== 0) {
currentGroup = [element];
result.push(currentGroup);

View File

@@ -8,6 +8,7 @@ import { canceled, onUnexpectedError } from 'vs/base/common/errors';
import { Emitter, Event, Listener } from 'vs/base/common/event';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { LinkedList } from 'vs/base/common/linkedList';
import { extUri as defaultExtUri, IExtUri } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
export function isThenable<T>(obj: unknown): obj is Promise<T> {
@@ -592,19 +593,21 @@ export class ResourceQueue implements IDisposable {
private readonly queues = new Map<string, Queue<void>>();
queueFor(resource: URI): Queue<void> {
const key = resource.toString();
if (!this.queues.has(key)) {
const queue = new Queue<void>();
queue.onFinished(() => {
queue.dispose();
queueFor(resource: URI, extUri: IExtUri = defaultExtUri): Queue<void> {
const key = extUri.getComparisonKey(resource);
let queue = this.queues.get(key);
if (!queue) {
queue = new Queue<void>();
Event.once(queue.onFinished)(() => {
queue?.dispose();
this.queues.delete(key);
});
this.queues.set(key, queue);
}
return this.queues.get(key)!;
return queue;
}
dispose(): void {

View File

@@ -548,6 +548,9 @@ export namespace Codicon {
export const runBelow = new Codicon('run-below', { fontCharacter: '\\ebbe' });
export const notebookTemplate = new Codicon('notebook-template', { fontCharacter: '\\ebbf' });
export const debugRerun = new Codicon('debug-rerun', { fontCharacter: '\\ebc0' });
export const workspaceTrusted = new Codicon('workspace-trusted', { fontCharacter: '\\ebc1' });
export const workspaceUntrusted = new Codicon('workspace-untrusted', { fontCharacter: '\\ebc2' });
export const workspaceUnknown = new Codicon('workspace-unknown', { fontCharacter: '\\ebc3' });
export const dropDownButton = new Codicon('drop-down-button', Codicon.chevronDown.definition);
}

View File

@@ -838,12 +838,8 @@ export class LcsDiff {
let modifiedStop = 0;
if (i > 0) {
const prevChange = changes[i - 1];
if (prevChange.originalLength > 0) {
originalStop = prevChange.originalStart + prevChange.originalLength;
}
if (prevChange.modifiedLength > 0) {
modifiedStop = prevChange.modifiedStart + prevChange.modifiedLength;
}
originalStop = prevChange.originalStart + prevChange.originalLength;
modifiedStop = prevChange.modifiedStart + prevChange.modifiedLength;
}
const checkOriginal = change.originalLength > 0;
@@ -868,7 +864,11 @@ export class LcsDiff {
break;
}
const score = this._boundaryScore(originalStart, change.originalLength, modifiedStart, change.modifiedLength);
const touchingPreviousChange = (originalStart === originalStop && modifiedStart === modifiedStop);
const score = (
(touchingPreviousChange ? 5 : 0)
+ this._boundaryScore(originalStart, change.originalLength, modifiedStart, change.modifiedLength)
);
if (score > bestScore) {
bestScore = score;
@@ -878,6 +878,14 @@ export class LcsDiff {
change.originalStart -= bestDelta;
change.modifiedStart -= bestDelta;
const mergedChangeArr: Array<DiffChange | null> = [null];
if (i > 0 && this.ChangesOverlap(changes[i - 1], changes[i], mergedChangeArr)) {
changes[i - 1] = mergedChangeArr[0]!;
changes.splice(i, 1);
i++;
continue;
}
}
// There could be multiple longest common substrings.

View File

@@ -365,28 +365,15 @@ export function matchesFuzzy2(pattern: string, word: string): IMatch[] | null {
return score ? createMatches(score) : null;
}
export function anyScore(pattern: string, lowPattern: string, _patternPos: number, word: string, lowWord: string, _wordPos: number): FuzzyScore {
const result = fuzzyScore(pattern, lowPattern, 0, word, lowWord, 0, true);
if (result) {
return result;
}
let matches: number[] = [];
let score = 0;
let idx = _wordPos;
for (let patternPos = 0; patternPos < lowPattern.length && patternPos < _maxLen; ++patternPos) {
const wordPos = lowWord.indexOf(lowPattern.charAt(patternPos), idx);
if (wordPos >= 0) {
score += 1;
matches.unshift(wordPos);
idx = wordPos + 1;
} else if (matches.length > 0) {
// once we have started matching things
// we need to match the remaining pattern
// characters
break;
export function anyScore(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number): FuzzyScore {
const max = Math.min(13, pattern.length);
for (; patternPos < max; patternPos++) {
const result = fuzzyScore(pattern, lowPattern, patternPos, word, lowWord, wordPos, false);
if (result) {
return result;
}
}
return [score, _wordPos, ...matches];
return [0, wordPos];
}
//#region --- fuzzyScore ---

View File

@@ -5,7 +5,6 @@
import { ParseError, Node, JSONPath, Segment, parseTree, findNodeAtLocation } from './json';
import { Edit, format, isEOL, FormattingOptions } from './jsonFormatter';
import { mergeSort } from 'vs/base/common/arrays';
export function removeProperty(text: string, path: JSONPath, formattingOptions: FormattingOptions): Edit[] {
@@ -156,7 +155,7 @@ export function applyEdit(text: string, edit: Edit): string {
}
export function applyEdits(text: string, edits: Edit[]): string {
let sortedEdits = mergeSort(edits, (a, b) => {
let sortedEdits = edits.slice(0).sort((a, b) => {
const diff = a.offset - b.offset;
if (diff === 0) {
return a.length - b.length;

View File

@@ -7,113 +7,117 @@
//@ts-check
/**
* @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}}
*/
function _definePolyfillMarks(timeOrigin) {
(function () {
const _data = [];
if (typeof timeOrigin === 'number') {
_data.push('code/timeOrigin', timeOrigin);
}
/**
* @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}}
*/
function _definePolyfillMarks(timeOrigin) {
function mark(name) {
_data.push(name, Date.now());
}
function getMarks() {
const result = [];
for (let i = 0; i < _data.length; i += 2) {
result.push({
name: _data[i],
startTime: _data[i + 1],
});
const _data = [];
if (typeof timeOrigin === 'number') {
_data.push('code/timeOrigin', timeOrigin);
}
return result;
function mark(name) {
_data.push(name, Date.now());
}
function getMarks() {
const result = [];
for (let i = 0; i < _data.length; i += 2) {
result.push({
name: _data[i],
startTime: _data[i + 1],
});
}
return result;
}
return { mark, getMarks };
}
return { mark, getMarks };
}
/**
* @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}}
*/
function _define() {
/**
* @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}}
*/
function _define() {
if (typeof performance === 'object' && typeof performance.mark === 'function') {
// in a browser context, reuse performance-util
if (typeof performance === 'object' && typeof performance.mark === 'function') {
// in a browser context, reuse performance-util
if (typeof performance.timeOrigin !== 'number' && !performance.timing) {
// safari & webworker: because there is no timeOrigin and no workaround
// we use the `Date.now`-based polyfill.
return _definePolyfillMarks();
if (typeof performance.timeOrigin !== 'number' && !performance.timing) {
// safari & webworker: because there is no timeOrigin and no workaround
// we use the `Date.now`-based polyfill.
return _definePolyfillMarks();
} else {
// use "native" performance for mark and getMarks
return {
mark(name) {
performance.mark(name);
},
getMarks() {
let timeOrigin = performance.timeOrigin;
if (typeof timeOrigin !== 'number') {
// safari: there is no timerOrigin but in renderers there is the timing-property
// see https://bugs.webkit.org/show_bug.cgi?id=174862
timeOrigin = performance.timing.navigationStart || performance.timing.redirectStart || performance.timing.fetchStart;
}
const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }];
for (const entry of performance.getEntriesByType('mark')) {
result.push({
name: entry.name,
startTime: Math.round(timeOrigin + entry.startTime)
});
}
return result;
}
};
}
} else if (typeof process === 'object') {
// node.js: use the normal polyfill but add the timeOrigin
// from the node perf_hooks API as very first mark
const timeOrigin = Math.round((require.nodeRequire || require)('perf_hooks').performance.timeOrigin);
return _definePolyfillMarks(timeOrigin);
} else {
// use "native" performance for mark and getMarks
return {
mark(name) {
performance.mark(name);
},
getMarks() {
let timeOrigin = performance.timeOrigin;
if (typeof timeOrigin !== 'number') {
// safari: there is no timerOrigin but in renderers there is the timing-property
// see https://bugs.webkit.org/show_bug.cgi?id=174862
timeOrigin = performance.timing.navigationStart || performance.timing.redirectStart || performance.timing.fetchStart;
}
const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }];
for (const entry of performance.getEntriesByType('mark')) {
result.push({
name: entry.name,
startTime: Math.round(timeOrigin + entry.startTime)
});
}
return result;
}
};
// unknown environment
console.trace('perf-util loaded in UNKNOWN environment');
return _definePolyfillMarks();
}
}
} else if (typeof process === 'object') {
// node.js: use the normal polyfill but add the timeOrigin
// from the node perf_hooks API as very first mark
const timeOrigin = Math.round((require.nodeRequire || require)('perf_hooks').performance.timeOrigin);
return _definePolyfillMarks(timeOrigin);
function _factory(sharedObj) {
if (!sharedObj.MonacoPerformanceMarks) {
sharedObj.MonacoPerformanceMarks = _define();
}
return sharedObj.MonacoPerformanceMarks;
}
// This module can be loaded in an amd and commonjs-context.
// Because we want both instances to use the same perf-data
// we store them globally
// eslint-disable-next-line no-var
var sharedObj;
if (typeof global === 'object') {
// nodejs
sharedObj = global;
} else if (typeof self === 'object') {
// browser
sharedObj = self;
} else {
// unknown environment
console.trace('perf-util loaded in UNKNOWN environment');
return _definePolyfillMarks();
sharedObj = {};
}
}
function _factory(sharedObj) {
if (!sharedObj.MonacoPerformanceMarks) {
sharedObj.MonacoPerformanceMarks = _define();
if (typeof define === 'function') {
// amd
define([], function () { return _factory(sharedObj); });
} else if (typeof module === 'object' && typeof module.exports === 'object') {
// commonjs
module.exports = _factory(sharedObj);
} else {
console.trace('perf-util defined in UNKNOWN context (neither requirejs or commonjs)');
sharedObj.perf = _factory(sharedObj);
}
return sharedObj.MonacoPerformanceMarks;
}
// This module can be loaded in an amd and commonjs-context.
// Because we want both instances to use the same perf-data
// we store them globally
// eslint-disable-next-line no-var
var sharedObj;
if (typeof global === 'object') {
// nodejs
sharedObj = global;
} else if (typeof self === 'object') {
// browser
sharedObj = self;
} else {
sharedObj = {};
}
if (typeof define === 'function') {
// amd
define([], function () { return _factory(sharedObj); });
} else if (typeof module === 'object' && typeof module.exports === 'object') {
// commonjs
module.exports = _factory(sharedObj);
} else {
console.trace('perf-util defined in UNKNOWN context (neither requirejs or commonjs)');
sharedObj.perf = _factory(sharedObj);
}
})();

View File

@@ -27,37 +27,38 @@ export interface IProcessEnvironment {
[key: string]: string;
}
/**
* This interface is intentionally not identical to node.js
* process because it also works in sandboxed environments
* where the process object is implemented differently. We
* define the properties here that we need for `platform`
* to work and nothing else.
*/
export interface INodeProcess {
platform: 'win32' | 'linux' | 'darwin';
platform: string;
env: IProcessEnvironment;
nextTick: Function;
nextTick?: (callback: (...args: any[]) => void) => void;
versions?: {
electron?: string;
};
sandboxed?: boolean; // Electron
sandboxed?: boolean;
type?: string;
cwd(): string;
cwd: () => string;
}
declare const process: INodeProcess;
declare const global: any;
declare const global: unknown;
declare const self: unknown;
interface INavigator {
userAgent: string;
language: string;
maxTouchPoints?: number;
}
declare const navigator: INavigator;
declare const self: any;
const _globals = (typeof self === 'object' ? self : typeof global === 'object' ? global : {} as any);
export const globals: any = (typeof self === 'object' ? self : typeof global === 'object' ? global : {});
let nodeProcess: INodeProcess | undefined = undefined;
if (typeof process !== 'undefined') {
// Native environment (non-sandboxed)
nodeProcess = process;
} else if (typeof _globals.vscode !== 'undefined') {
} else if (typeof globals.vscode !== 'undefined') {
// Native environment (sandboxed)
nodeProcess = _globals.vscode.process;
nodeProcess = globals.vscode.process;
}
const isElectronRenderer = typeof nodeProcess?.versions?.electron === 'string' && nodeProcess.type === 'renderer';
@@ -83,6 +84,13 @@ export const browserCodeLoadingCacheStrategy: 'none' | 'code' | 'bypassHeatCheck
})();
export const isPreferringBrowserCodeLoad = typeof browserCodeLoadingCacheStrategy === 'string';
interface INavigator {
userAgent: string;
language: string;
maxTouchPoints?: number;
}
declare const navigator: INavigator;
// Web environment
if (typeof navigator === 'object' && !isElectronRenderer) {
_userAgent = navigator.userAgent;
@@ -197,10 +205,8 @@ export const locale = _locale;
*/
export const translationsConfigFile = _translationsConfigFile;
export const globals: any = _globals;
interface ISetImmediate {
(callback: (...args: any[]) => void): void;
(callback: (...args: unknown[]) => void): void;
}
export const setImmediate: ISetImmediate = (function defineSetImmediate() {
@@ -235,11 +241,11 @@ export const setImmediate: ISetImmediate = (function defineSetImmediate() {
globals.postMessage({ vscodeSetImmediateId: myId }, '*');
};
}
if (nodeProcess && typeof nodeProcess.nextTick === 'function') {
if (typeof nodeProcess?.nextTick === 'function') {
return nodeProcess.nextTick.bind(nodeProcess);
}
const _promise = Promise.resolve();
return (callback: (...args: any[]) => void) => _promise.then(callback);
return (callback: (...args: unknown[]) => void) => _promise.then(callback);
})();
export const enum OperatingSystem {

View File

@@ -5,26 +5,27 @@
import { isWindows, isMacintosh, setImmediate, globals, INodeProcess } from 'vs/base/common/platform';
declare const process: INodeProcess;
let safeProcess: INodeProcess;
let safeProcess: INodeProcess & { nextTick: (callback: (...args: any[]) => void) => void; };
// Native node.js environment
declare const process: INodeProcess;
if (typeof process !== 'undefined') {
safeProcess = process;
safeProcess = {
get platform() { return process.platform; },
get env() { return process.env; },
cwd() { return process.env['VSCODE_CWD'] || process.cwd(); },
nextTick(callback: (...args: any[]) => void): void { return process.nextTick!(callback); }
};
}
// Native sandbox environment
else if (typeof globals.vscode !== 'undefined') {
const sandboxProcess: INodeProcess = globals.vscode.process;
safeProcess = {
// Supported
get platform(): 'win32' | 'linux' | 'darwin' { return globals.vscode.process.platform; },
get env() { return globals.vscode.process.env; },
nextTick(callback: (...args: any[]) => void): void { return setImmediate(callback); },
// Unsupported
cwd(): string { return globals.vscode.process.env['VSCODE_CWD'] || globals.vscode.process.execPath.substr(0, globals.vscode.process.execPath.lastIndexOf(globals.vscode.process.platform === 'win32' ? '\\' : '/')); }
get platform() { return sandboxProcess.platform; },
get env() { return sandboxProcess.env; },
cwd() { return sandboxProcess.cwd(); },
nextTick(callback: (...args: any[]) => void): void { return setImmediate(callback); }
};
}
@@ -33,16 +34,39 @@ else {
safeProcess = {
// Supported
get platform(): 'win32' | 'linux' | 'darwin' { return isWindows ? 'win32' : isMacintosh ? 'darwin' : 'linux'; },
get platform() { return isWindows ? 'win32' : isMacintosh ? 'darwin' : 'linux'; },
nextTick(callback: (...args: any[]) => void): void { return setImmediate(callback); },
// Unsupported
get env() { return Object.create(null); },
cwd(): string { return '/'; }
cwd() { return '/'; }
};
}
/**
* Provides safe access to the `cwd` property in node.js, sandboxed or web
* environments.
*
* Note: in web, this property is hardcoded to be `/`.
*/
export const cwd = safeProcess.cwd;
/**
* Provides safe access to the `env` property in node.js, sandboxed or web
* environments.
*
* Note: in web, this property is hardcoded to be `{}`.
*/
export const env = safeProcess.env;
/**
* Provides safe access to the `platform` property in node.js, sandboxed or web
* environments.
*/
export const platform = safeProcess.platform;
/**
* Provides safe access to the `nextTick` method in node.js, sandboxed or web
* environments.
*/
export const nextTick = safeProcess.nextTick;

View File

@@ -20,6 +20,8 @@ export function buildReplaceStringWithCasePreserved(matches: string[] | null, pa
return pattern.toLowerCase();
} else if (strings.containsUppercaseCharacter(matches[0][0]) && pattern.length > 0) {
return pattern[0].toUpperCase() + pattern.substr(1);
} else if (matches[0][0].toUpperCase() !== matches[0][0] && pattern.length > 0) {
return pattern[0].toLowerCase() + pattern.substr(1);
} else {
// we don't understand its pattern yet.
return pattern;

View File

@@ -101,19 +101,19 @@ export interface WriteableStream<T> extends ReadableStream<T> {
/**
* Signals an error to the consumer of the stream via the
* on('error') handler if the stream is flowing.
*
* NOTE: call `end` to signal that the stream has ended,
* this DOES NOT happen automatically from `error`.
*/
error(error: Error): void;
/**
* Signals the end of the stream to the consumer. If the
* result is not an error, will trigger the on('data') event
* result is provided, will trigger the on('data') event
* listener if the stream is flowing and buffer the data
* otherwise until the stream is flowing.
*
* In case of an error, the on('error') event will be used
* if the stream is flowing.
*/
end(result?: T | Error): void;
end(result?: T): void;
}
/**
@@ -267,15 +267,13 @@ class WriteableStreamImpl<T> implements WriteableStream<T> {
}
}
end(result?: T | Error): void {
end(result?: T): void {
if (this.state.destroyed) {
return;
}
// end with data or error if provided
if (result instanceof Error) {
this.error(result);
} else if (typeof result !== 'undefined') {
// end with data if provided
if (typeof result !== 'undefined') {
this.write(result);
}

View File

@@ -50,6 +50,13 @@ export function isNumber(obj: unknown): obj is number {
return (typeof obj === 'number' && !isNaN(obj));
}
/**
* @returns whether the provided parameter is an Iterable, casting to the given generic
*/
export function isIterable<T>(obj: unknown): obj is Iterable<T> {
return !!obj && typeof (obj as any)[Symbol.iterator] === 'function';
}
/**
* @returns whether the provided parameter is a JavaScript Boolean or not.
*/

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs';
import { promisify } from 'util';
import { rtrim } from 'vs/base/common/strings';
import { sep, join, normalize, dirname, basename } from 'vs/base/common/path';
import { readdirSync } from 'vs/base/node/pfs';
@@ -52,7 +53,11 @@ export function realcaseSync(path: string): string | null {
export async function realpath(path: string): Promise<string> {
try {
return await fs.promises.realpath(path);
// DO NOT USE `fs.promises.realpath` here as it internally
// calls `fs.native.realpath` which will result in subst
// drives to be resolved to their target on Windows
// https://github.com/microsoft/vscode/issues/118562
return await promisify(fs.realpath)(path);
} catch (error) {
// We hit an error calling fs.realpath(). Since fs.realpath() is doing some path normalization

View File

@@ -6,27 +6,13 @@
import * as fs from 'fs';
import { tmpdir } from 'os';
import { join } from 'vs/base/common/path';
import { Queue } from 'vs/base/common/async';
import { ResourceQueue } from 'vs/base/common/async';
import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import { Event } from 'vs/base/common/event';
import { isEqualOrParent, isRootOrDriveLetter } from 'vs/base/common/extpath';
import { generateUuid } from 'vs/base/common/uuid';
import { normalizeNFC } from 'vs/base/common/normalization';
//#region Constants
// See https://github.com/microsoft/vscode/issues/30180
const WIN32_MAX_FILE_SIZE = 300 * 1024 * 1024; // 300 MB
const GENERAL_MAX_FILE_SIZE = 16 * 1024 * 1024 * 1024; // 16 GB
// See https://github.com/v8/v8/blob/5918a23a3d571b9625e5cce246bdd5b46ff7cd8b/src/heap/heap.cc#L149
const WIN32_MAX_HEAP_SIZE = 700 * 1024 * 1024; // 700 MB
const GENERAL_MAX_HEAP_SIZE = 700 * 2 * 1024 * 1024; // 1400 MB
export const MAX_FILE_SIZE = process.arch === 'ia32' ? WIN32_MAX_FILE_SIZE : GENERAL_MAX_FILE_SIZE;
export const MAX_HEAP_SIZE = process.arch === 'ia32' ? WIN32_MAX_HEAP_SIZE : GENERAL_MAX_HEAP_SIZE;
//#endregion
import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
//#region rimraf
@@ -361,6 +347,11 @@ export namespace SymlinkSupport {
//#region Write File
// According to node.js docs (https://nodejs.org/docs/v6.5.0/api/fs.html#fs_fs_writefile_file_data_options_callback)
// it is not safe to call writeFile() on the same path multiple times without waiting for the callback to return.
// Therefor we use a Queue on the path that is given to us to sequentialize calls to the same path properly.
const writeQueues = new ResourceQueue();
/**
* Same as `fs.writeFile` but with an additional call to
* `fs.fdatasync` after writing to ensure changes are
@@ -373,47 +364,13 @@ export function writeFile(path: string, data: Buffer, options?: IWriteFileOption
export function writeFile(path: string, data: Uint8Array, options?: IWriteFileOptions): Promise<void>;
export function writeFile(path: string, data: string | Buffer | Uint8Array, options?: IWriteFileOptions): Promise<void>;
export function writeFile(path: string, data: string | Buffer | Uint8Array, options?: IWriteFileOptions): Promise<void> {
const queueKey = toQueueKey(path);
return ensureWriteFileQueue(queueKey).queue(() => {
return writeQueues.queueFor(URI.file(path), extUriBiasedIgnorePathCase).queue(() => {
const ensuredOptions = ensureWriteOptions(options);
return new Promise((resolve, reject) => doWriteFileAndFlush(path, data, ensuredOptions, error => error ? reject(error) : resolve()));
});
}
// According to node.js docs (https://nodejs.org/docs/v6.5.0/api/fs.html#fs_fs_writefile_file_data_options_callback)
// it is not safe to call writeFile() on the same path multiple times without waiting for the callback to return.
// Therefor we use a Queue on the path that is given to us to sequentialize calls to the same path properly.
const writeFilePathQueues: Map<string, Queue<void>> = new Map();
function toQueueKey(path: string): string {
let queueKey = path;
if (isWindows || isMacintosh) {
queueKey = queueKey.toLowerCase(); // accommodate for case insensitive file systems
}
return queueKey;
}
function ensureWriteFileQueue(queueKey: string): Queue<void> {
const existingWriteFileQueue = writeFilePathQueues.get(queueKey);
if (existingWriteFileQueue) {
return existingWriteFileQueue;
}
const writeFileQueue = new Queue<void>();
writeFilePathQueues.set(queueKey, writeFileQueue);
const onFinish = Event.once(writeFileQueue.onFinished);
onFinish(() => {
writeFilePathQueues.delete(queueKey);
writeFileQueue.dispose();
});
return writeFileQueue;
}
export interface IWriteFileOptions {
mode?: number;
flag?: string;
@@ -607,9 +564,6 @@ async function doCopy(source: string, target: string, payload: ICopyPayload): Pr
// Symlink
if (symbolicLink) {
if (symbolicLink.dangling) {
return; // do not copy dangling symbolic links (https://github.com/microsoft/vscode/issues/111621)
}
// Try to re-create the symlink unless `preserveSymlinks: false`
if (payload.options.preserveSymlinks) {
@@ -620,6 +574,10 @@ async function doCopy(source: string, target: string, payload: ICopyPayload): Pr
console.warn('[node.js fs] copy of symlink failed: ', error);
}
}
if (symbolicLink.dangling) {
return; // skip dangling symbolic links from here on (https://github.com/microsoft/vscode/issues/111621)
}
}
// Folder

View File

@@ -6,7 +6,6 @@
import * as pfs from 'vs/base/node/pfs';
import * as os from 'os';
import * as path from 'vs/base/common/path';
import { env } from 'vs/base/common/process';
// This is required, since parseInt("7-preview") will return 7.
const IntRegex: RegExp = /^\d+$/;
@@ -103,17 +102,17 @@ function getProgramFilesPath(
if (!useAlternateBitness) {
// Just use the native system bitness
return env.ProgramFiles || null;
return process.env.ProgramFiles || null;
}
// We might be a 64-bit process looking for 32-bit program files
if (processArch === Arch.x64) {
return env['ProgramFiles(x86)'] || null;
return process.env['ProgramFiles(x86)'] || null;
}
// We might be a 32-bit process looking for 64-bit program files
if (osArch === Arch.x64) {
return env.ProgramW6432 || null;
return process.env.ProgramW6432 || null;
}
// We're a 32-bit process on 32-bit Windows, there is no other Program Files dir
@@ -194,12 +193,12 @@ async function findPSCoreWindowsInstallation(
async function findPSCoreMsix({ findPreview }: { findPreview?: boolean } = {}): Promise<IPossiblePowerShellExe | null> {
// We can't proceed if there's no LOCALAPPDATA path
if (!env.LOCALAPPDATA) {
if (!process.env.LOCALAPPDATA) {
return null;
}
// Find the base directory for MSIX application exe shortcuts
const msixAppDir = path.join(env.LOCALAPPDATA, 'Microsoft', 'WindowsApps');
const msixAppDir = path.join(process.env.LOCALAPPDATA, 'Microsoft', 'WindowsApps');
if (!await pfs.SymlinkSupport.existsDirectory(msixAppDir)) {
return null;
@@ -211,15 +210,11 @@ async function findPSCoreMsix({ findPreview }: { findPreview?: boolean } = {}):
: { pwshMsixDirRegex: PwshMsixRegex, pwshMsixName: 'PowerShell (Store)' };
// We should find only one such application, so return on the first one
try {
for (const subdir of await pfs.readdir(msixAppDir)) {
if (pwshMsixDirRegex.test(subdir)) {
const pwshMsixPath = path.join(msixAppDir, subdir, 'pwsh.exe');
return new PossiblePowerShellExe(pwshMsixPath, pwshMsixName);
}
for (const subdir of await pfs.readdir(msixAppDir)) {
if (pwshMsixDirRegex.test(subdir)) {
const pwshMsixPath = path.join(msixAppDir, subdir, 'pwsh.exe');
return new PossiblePowerShellExe(pwshMsixPath, pwshMsixName);
}
} catch (err) {
console.warn(`Unable to read MSIX directory (${msixAppDir}) because of the following error: ${err}`);
}
// If we find nothing, return null
@@ -234,7 +229,7 @@ function findPSCoreDotnetGlobalTool(): IPossiblePowerShellExe {
function findWinPS(): IPossiblePowerShellExe | null {
const winPSPath = path.join(
env.windir!,
process.env.windir!,
processArch === Arch.x86 && osArch !== Arch.x86 ? 'SysNative' : 'System32',
'WindowsPowerShell', 'v1.0', 'powershell.exe');

View File

@@ -8,6 +8,7 @@ import * as fs from 'fs';
import * as pfs from 'vs/base/node/pfs';
import * as cp from 'child_process';
import * as nls from 'vs/nls';
import * as process from 'vs/base/common/process';
import * as Types from 'vs/base/common/types';
import { IStringDictionary } from 'vs/base/common/collections';
import * as Objects from 'vs/base/common/objects';

View File

@@ -13,7 +13,7 @@ import * as processes from 'vs/base/node/processes';
* shell that the terminal uses by default.
* @param p The platform to detect the shell of.
*/
export async function getSystemShell(p: platform.Platform, env = process.env as platform.IProcessEnvironment): Promise<string> {
export async function getSystemShell(p: platform.Platform, env: platform.IProcessEnvironment): Promise<string> {
if (p === platform.Platform.Windows) {
if (platform.isWindows) {
return getSystemShellWindows();
@@ -25,7 +25,7 @@ export async function getSystemShell(p: platform.Platform, env = process.env as
return getSystemShellUnixLike(p, env);
}
export function getSystemShellSync(p: platform.Platform, env = process.env as platform.IProcessEnvironment): string {
export function getSystemShellSync(p: platform.Platform, env: platform.IProcessEnvironment): string {
if (p === platform.Platform.Windows) {
if (platform.isWindows) {
return getSystemShellWindowsSync(env);
@@ -45,7 +45,7 @@ function getSystemShellUnixLike(p: platform.Platform, env: platform.IProcessEnvi
}
if (!_TERMINAL_DEFAULT_SHELL_UNIX_LIKE) {
let unixLikeTerminal: string;
let unixLikeTerminal: string | undefined;
if (platform.isWindows) {
unixLikeTerminal = '/bin/bash'; // for WSL
} else {

View File

@@ -18,13 +18,31 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { Platform, platform } from 'vs/base/common/platform';
export class NodeSocket implements ISocket {
public readonly socket: Socket;
private readonly _errorListener: (err: any) => void;
constructor(socket: Socket) {
this.socket = socket;
this._errorListener = (err: any) => {
if (err) {
if (err.code === 'EPIPE') {
// An EPIPE exception at the wrong time can lead to a renderer process crash
// so ignore the error since the socket will fire the close event soon anyways:
// > https://nodejs.org/api/errors.html#errors_common_system_errors
// > EPIPE (Broken pipe): A write on a pipe, socket, or FIFO for which there is no
// > process to read the data. Commonly encountered at the net and http layers,
// > indicative that the remote side of the stream being written to has been closed.
return;
}
onUnexpectedError(err);
}
};
this.socket.on('error', this._errorListener);
}
public dispose(): void {
this.socket.off('error', this._errorListener);
this.socket.destroy();
}
@@ -62,7 +80,20 @@ export class NodeSocket implements ISocket {
// > However, the false return value is only advisory and the writable stream will unconditionally
// > accept and buffer chunk even if it has not been allowed to drain.
try {
this.socket.write(<Buffer>buffer.buffer);
this.socket.write(<Buffer>buffer.buffer, (err: any) => {
if (err) {
if (err.code === 'EPIPE') {
// An EPIPE exception at the wrong time can lead to a renderer process crash
// so ignore the error since the socket will fire the close event soon anyways:
// > https://nodejs.org/api/errors.html#errors_common_system_errors
// > EPIPE (Broken pipe): A write on a pipe, socket, or FIFO for which there is no
// > process to read the data. Commonly encountered at the net and http layers,
// > indicative that the remote side of the stream being written to has been closed.
return;
}
onUnexpectedError(err);
}
});
} catch (err) {
if (err.code === 'EPIPE') {
// An EPIPE exception at the wrong time can lead to a renderer process crash

View File

@@ -6,7 +6,7 @@
import * as assert from 'assert';
import { Client } from 'vs/base/parts/ipc/node/ipc.cp';
import { TestServiceClient } from './testService';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { getPathFromAmdModule } from 'vs/base/test/node/testUtils';
function createClient(): Client {
return new Client(getPathFromAmdModule(require, 'bootstrap-fork'), {

View File

@@ -7,7 +7,7 @@
position: absolute;
width: 600px;
z-index: 2000;
padding-bottom: 6px;
padding: 0 1px 6px 1px;
left: 50%;
margin-left: -300px;
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/quickInput';
import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent, QuickPickInput, IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent, NO_KEY_MODS, ItemActivation } from 'vs/base/parts/quickinput/common/quickInput';
import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent, QuickPickInput, IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent, NO_KEY_MODS, ItemActivation, QuickInputHideReason, IQuickInputHideEvent } from 'vs/base/parts/quickinput/common/quickInput';
import * as dom from 'vs/base/browser/dom';
import { CancellationToken } from 'vs/base/common/cancellation';
import { QuickInputList, QuickInputListFocus } from './quickInputList';
@@ -31,6 +31,7 @@ import { registerCodicon, Codicon } from 'vs/base/common/codicons';
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { escape } from 'vs/base/common/strings';
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
import { isString } from 'vs/base/common/types';
export interface IQuickInputOptions {
idPrefix: string;
@@ -133,6 +134,7 @@ type Visibilities = {
};
class QuickInput extends Disposable implements IQuickInput {
protected static readonly noPromptMessage = localize('inputModeEntry', "Press 'Enter' to confirm your input or 'Escape' to cancel");
private _title: string | undefined;
private _description: string | undefined;
@@ -144,9 +146,14 @@ class QuickInput extends Disposable implements IQuickInput {
private _busy = false;
private _ignoreFocusOut = false;
private _buttons: IQuickInputButton[] = [];
protected noValidationMessage = QuickInput.noPromptMessage;
private _validationMessage: string | undefined;
private _lastValidationMessage: string | undefined;
private _severity: Severity = Severity.Ignore;
private _lastSeverity: Severity | undefined;
private buttonsUpdated = false;
private readonly onDidTriggerButtonEmitter = this._register(new Emitter<IQuickInputButton>());
private readonly onDidHideEmitter = this._register(new Emitter<void>());
private readonly onDidHideEmitter = this._register(new Emitter<IQuickInputHideEvent>());
private readonly onDisposeEmitter = this._register(new Emitter<void>());
protected readonly visibleDisposables = this._register(new DisposableStore());
@@ -241,6 +248,24 @@ class QuickInput extends Disposable implements IQuickInput {
this.update();
}
get validationMessage() {
return this._validationMessage;
}
set validationMessage(validationMessage: string | undefined) {
this._validationMessage = validationMessage;
this.update();
}
get severity() {
return this._severity;
}
set severity(severity: Severity) {
this._severity = severity;
this.update();
}
readonly onDidTriggerButton = this.onDidTriggerButtonEmitter.event;
show(): void {
@@ -266,10 +291,10 @@ class QuickInput extends Disposable implements IQuickInput {
this.ui.hide();
}
didHide(): void {
didHide(reason = QuickInputHideReason.Other): void {
this.visible = false;
this.visibleDisposables.clear();
this.onDidHideEmitter.fire();
this.onDidHideEmitter.fire({ reason });
}
readonly onDidHide = this.onDidHideEmitter.event;
@@ -328,6 +353,16 @@ class QuickInput extends Disposable implements IQuickInput {
this.ui.ignoreFocusOut = this.ignoreFocusOut;
this.ui.setEnabled(this.enabled);
this.ui.setContextKey(this.contextKey);
const validationMessage = this.validationMessage || this.noValidationMessage;
if (this._lastValidationMessage !== validationMessage) {
this._lastValidationMessage = validationMessage;
dom.reset(this.ui.message, ...renderLabelWithIcons(escape(validationMessage)));
}
if (this._lastSeverity !== this.severity) {
this._lastSeverity = this.severity;
this.showMessageDecoration(this.severity);
}
}
private getTitle() {
@@ -359,7 +394,7 @@ class QuickInput extends Disposable implements IQuickInput {
protected showMessageDecoration(severity: Severity) {
this.ui.inputBox.showDecoration(severity);
if (severity === Severity.Error) {
if (severity !== Severity.Ignore) {
const styles = this.ui.inputBox.stylesForType(severity);
this.ui.message.style.color = styles.foreground ? `${styles.foreground}` : '';
this.ui.message.style.backgroundColor = styles.background ? `${styles.background}` : '';
@@ -414,8 +449,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
private readonly onDidTriggerItemButtonEmitter = this._register(new Emitter<IQuickPickItemButtonEvent<T>>());
private _valueSelection: Readonly<[number, number]> | undefined;
private valueSelectionUpdated = true;
private _validationMessage: string | undefined;
private _lastValidationMessage: string | undefined;
private _ok: boolean | 'default' = 'default';
private _customButton = false;
private _customButtonLabel: string | undefined;
@@ -587,15 +620,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this.update();
}
get validationMessage() {
return this._validationMessage;
}
set validationMessage(validationMessage: string | undefined) {
this._validationMessage = validationMessage;
this.update();
}
get customButton() {
return this._customButton;
}
@@ -964,12 +988,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this.selectedItemsToConfirm = null;
}
}
const validationMessage = this.validationMessage || '';
if (this._lastValidationMessage !== validationMessage) {
this._lastValidationMessage = validationMessage;
dom.reset(this.ui.message, ...renderLabelWithIcons(escape(validationMessage)));
this.showMessageDecoration(this.validationMessage ? Severity.Error : Severity.Ignore);
}
this.ui.customButton.label = this.customLabel || '';
this.ui.customButton.element.title = this.customHover || '';
this.ui.setComboboxAccessibility(true);
@@ -987,18 +1005,12 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
}
class InputBox extends QuickInput implements IInputBox {
private static readonly noPromptMessage = localize('inputModeEntry', "Press 'Enter' to confirm your input or 'Escape' to cancel");
private _value = '';
private _valueSelection: Readonly<[number, number]> | undefined;
private valueSelectionUpdated = true;
private _placeholder: string | undefined;
private _password = false;
private _prompt: string | undefined;
private noValidationMessage = InputBox.noPromptMessage;
private _validationMessage: string | undefined;
private _lastValidationMessage: string | undefined;
private readonly onDidValueChangeEmitter = this._register(new Emitter<string>());
private readonly onDidAcceptEmitter = this._register(new Emitter<void>());
@@ -1043,16 +1055,7 @@ class InputBox extends QuickInput implements IInputBox {
this._prompt = prompt;
this.noValidationMessage = prompt
? localize('inputModeEntryDescription', "{0} (Press 'Enter' to confirm or 'Escape' to cancel)", prompt)
: InputBox.noPromptMessage;
this.update();
}
get validationMessage() {
return this._validationMessage;
}
set validationMessage(validationMessage: string | undefined) {
this._validationMessage = validationMessage;
: QuickInput.noPromptMessage;
this.update();
}
@@ -1100,12 +1103,7 @@ class InputBox extends QuickInput implements IInputBox {
if (this.ui.inputBox.password !== this.password) {
this.ui.inputBox.password = this.password;
}
const validationMessage = this.validationMessage || this.noValidationMessage;
if (this._lastValidationMessage !== validationMessage) {
this._lastValidationMessage = validationMessage;
dom.reset(this.ui.message, ...renderLabelWithIcons(validationMessage));
this.showMessageDecoration(this.validationMessage ? Severity.Error : Severity.Ignore);
}
}
}
@@ -1222,9 +1220,6 @@ export class QuickInputController extends Disposable {
const message = dom.append(extraContainer, $(`#${this.idPrefix}message.quick-input-message`));
const progressBar = new ProgressBar(container);
progressBar.getContainer().classList.add('quick-input-progress');
const list = this._register(new QuickInputList(container, this.idPrefix + 'list', this.options));
this._register(list.onChangedAllVisibleChecked(checked => {
checkAll.checked = checked;
@@ -1250,6 +1245,9 @@ export class QuickInputController extends Disposable {
}
}));
const progressBar = new ProgressBar(container);
progressBar.getContainer().classList.add('quick-input-progress');
const focusTracker = dom.trackFocus(container);
this._register(focusTracker);
this._register(dom.addDisposableListener(container, dom.EventType.FOCUS, e => {
@@ -1257,7 +1255,7 @@ export class QuickInputController extends Disposable {
}, true));
this._register(focusTracker.onDidBlur(() => {
if (!this.getUI().ignoreFocusOut && !this.options.ignoreFocusOut()) {
this.hide();
this.hide(QuickInputHideReason.Blur);
}
this.previousFocusElement = undefined;
}));
@@ -1273,7 +1271,7 @@ export class QuickInputController extends Disposable {
break;
case KeyCode.Escape:
dom.EventHelper.stop(e, true);
this.hide();
this.hide(QuickInputHideReason.Gesture);
break;
case KeyCode.Tab:
if (!event.altKey && !event.ctrlKey && !event.metaKey) {
@@ -1320,8 +1318,8 @@ export class QuickInputController extends Disposable {
message,
customButtonContainer,
customButton,
progressBar,
list,
progressBar,
onDidAccept: this.onDidAcceptEmitter.event,
onDidCustom: this.onDidCustomEmitter.event,
onDidTriggerButton: this.onDidTriggerButtonEmitter.event,
@@ -1408,6 +1406,7 @@ export class QuickInputController extends Disposable {
resolve(undefined);
}),
];
input.title = options.title;
input.canSelectMany = !!options.canPickMany;
input.placeholder = options.placeHolder;
input.ignoreFocusOut = !!options.ignoreFocusLost;
@@ -1438,6 +1437,22 @@ export class QuickInputController extends Disposable {
});
}
private setValidationOnInput(input: IInputBox, validationResult: string | {
content: string;
severity: Severity;
} | null | undefined) {
if (validationResult && isString(validationResult)) {
input.severity = Severity.Error;
input.validationMessage = validationResult;
} else if (validationResult && !isString(validationResult)) {
input.severity = validationResult.severity;
input.validationMessage = validationResult.content;
} else {
input.severity = Severity.Ignore;
input.validationMessage = undefined;
}
}
input(options: IInputOptions = {}, token: CancellationToken = CancellationToken.None): Promise<string | undefined> {
return new Promise<string | undefined>((resolve) => {
if (token.isCancellationRequested) {
@@ -1458,7 +1473,7 @@ export class QuickInputController extends Disposable {
}
validation.then(result => {
if (value === validationValue) {
input.validationMessage = result || undefined;
this.setValidationOnInput(input, result);
}
});
}),
@@ -1469,11 +1484,11 @@ export class QuickInputController extends Disposable {
validationValue = value;
}
validation.then(result => {
if (!result) {
if (!result || (!isString(result) && result.severity !== Severity.Error)) {
resolve(value);
input.hide();
} else if (value === validationValue) {
input.validationMessage = result;
this.setValidationOnInput(input, result);
}
});
}),
@@ -1485,6 +1500,8 @@ export class QuickInputController extends Disposable {
resolve(undefined);
}),
];
input.title = options.title;
input.value = options.value || '';
input.valueSelection = options.valueSelection;
input.prompt = options.prompt;
@@ -1600,7 +1617,7 @@ export class QuickInputController extends Disposable {
}
}
hide() {
hide(reason?: QuickInputHideReason) {
const controller = this.controller;
if (controller) {
const focusChanged = !this.ui?.container.contains(document.activeElement);
@@ -1615,7 +1632,7 @@ export class QuickInputController extends Disposable {
this.options.returnFocus();
}
}
controller.didHide();
controller.didHide(reason);
}
}

View File

@@ -10,6 +10,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { IMatch } from 'vs/base/common/filters';
import { IItemAccessor } from 'vs/base/common/fuzzyScorer';
import { Schemas } from 'vs/base/common/network';
import Severity from 'vs/base/common/severity';
export interface IQuickPickItemHighlights {
label?: IMatch[];
@@ -58,6 +59,11 @@ export interface IQuickNavigateConfiguration {
export interface IPickOptions<T extends IQuickPickItem> {
/**
* an optional string to show as the title of the quick input
*/
title?: string;
/**
* an optional string to show as placeholder in the input box to guide the user what she picks on
*/
@@ -115,6 +121,11 @@ export interface IPickOptions<T extends IQuickPickItem> {
export interface IInputOptions {
/**
* an optional string to show as the title of the quick input
*/
title?: string;
/**
* the value to prefill in the input box
*/
@@ -145,12 +156,34 @@ export interface IInputOptions {
/**
* an optional function that is used to validate user input.
*/
validateInput?: (input: string) => Promise<string | null | undefined>;
validateInput?: (input: string) => Promise<string | null | undefined | { content: string, severity: Severity }>;
}
export enum QuickInputHideReason {
/**
* Focus moved away from the quick input.
*/
Blur = 1,
/**
* An explicit user gesture, e.g. pressing Escape key.
*/
Gesture,
/**
* Anything else.
*/
Other
}
export interface IQuickInputHideEvent {
reason: QuickInputHideReason;
}
export interface IQuickInput extends IDisposable {
readonly onDidHide: Event<void>;
readonly onDidHide: Event<IQuickInputHideEvent>;
readonly onDispose: Event<void>;
title: string | undefined;
@@ -301,6 +334,8 @@ export interface IInputBox extends IQuickInput {
prompt: string | undefined;
validationMessage: string | undefined;
severity: Severity;
}
export interface IQuickInputButton {

View File

@@ -22,6 +22,8 @@
/**
* A minimal set of methods exposed from Electron's `ipcRenderer`
* to support communication to main process.
*
* @type {import('../electron-sandbox/electronTypes').IpcRenderer}
*/
ipcRenderer: {
@@ -49,34 +51,46 @@
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
*/
on(channel, listener) {
if (validateIPC(channel)) {
ipcRenderer.on(channel, listener);
return this;
}
},
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
*/
once(channel, listener) {
if (validateIPC(channel)) {
ipcRenderer.once(channel, listener);
return this;
}
},
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
*/
removeListener(channel, listener) {
if (validateIPC(channel)) {
ipcRenderer.removeListener(channel, listener);
return this;
}
}
},
/**
* @type {import('../electron-sandbox/globals').IpcMessagePort}
*/
ipcMessagePort: {
/**
@@ -106,6 +120,8 @@
/**
* Support for subset of methods of Electron's `webFrame` type.
*
* @type {import('../electron-sandbox/electronTypes').WebFrame}
*/
webFrame: {
@@ -121,6 +137,8 @@
/**
* Support for subset of methods of Electron's `crashReporter` type.
*
* @type {import('../electron-sandbox/electronTypes').CrashReporter}
*/
crashReporter: {
@@ -138,6 +156,8 @@
*
* Note: when `sandbox` is enabled, the only properties available
* are https://github.com/electron/electron/blob/master/docs/api/process.md#sandbox
*
* @type {import('../electron-sandbox/globals').ISandboxNodeProcess}
*/
process: {
get platform() { return process.platform; },
@@ -146,6 +166,21 @@
get versions() { return process.versions; },
get type() { return 'renderer'; },
get execPath() { return process.execPath; },
get sandboxed() { return process.sandboxed; },
/**
* @returns {string}
*/
cwd() {
return process.env['VSCODE_CWD'] || process.execPath.substr(0, process.execPath.lastIndexOf(process.platform === 'win32' ? '\\' : '/'));
},
/**
* @returns {Promise<typeof process.env>}
*/
getShellEnv() {
return shellEnv;
},
/**
* @param {{[key: string]: string}} userEnv
@@ -164,20 +199,17 @@
/**
* @param {string} type
* @param {() => void} callback
* @param {Function} callback
* @returns {import('../electron-sandbox/globals').ISandboxNodeProcess}
*/
on(type, callback) {
if (validateProcessEventType(type)) {
// @ts-ignore
process.on(type, callback);
return this;
}
}
},
/**
* Some information about the context we are running in.
*/
context: {
get sandbox() { return process.sandboxed; }
}
};
@@ -226,8 +258,8 @@
return true;
}
/** @type {Promise<void> | undefined} */
let resolvedEnv = undefined;
/** @type {Promise<typeof process.env> | undefined} */
let shellEnv = undefined;
/**
* If VSCode is not run from a terminal, we should resolve additional
@@ -238,28 +270,29 @@
* @param {{[key: string]: string}} userEnv
* @returns {Promise<void>}
*/
function resolveEnv(userEnv) {
if (!resolvedEnv) {
async function resolveEnv(userEnv) {
if (!shellEnv) {
// Apply `userEnv` directly
Object.assign(process.env, userEnv);
// Resolve `shellEnv` from the main side
resolvedEnv = new Promise(function (resolve) {
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) {
shellEnv = new Promise(function (resolve) {
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnvResult) {
if (!process.env['VSCODE_SKIP_PROCESS_ENV_PATCHING'] /* TODO@bpasero for https://github.com/microsoft/vscode/issues/108804 */) {
// Assign all keys of the shell environment to our process environment
// But make sure that the user environment wins in the end over shell environment
Object.assign(process.env, shellEnvResult, userEnv);
}
// Assign all keys of the shell environment to our process environment
// But make sure that the user environment wins in the end
Object.assign(process.env, shellEnv, userEnv);
resolve();
resolve({ ...process.env, ...shellEnvResult, ...userEnv });
});
ipcRenderer.send('vscode:fetchShellEnv');
});
}
return resolvedEnv;
await shellEnv;
}
//#endregion

View File

@@ -3,19 +3,19 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { globals, IProcessEnvironment } from 'vs/base/common/platform';
import { globals, INodeProcess, IProcessEnvironment } from 'vs/base/common/platform';
import { ProcessMemoryInfo, CrashReporter, IpcRenderer, WebFrame } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes';
/**
* In sandboxed renderers we cannot expose all of the `process` global of node.js
*/
export interface IPartialNodeProcess {
export interface ISandboxNodeProcess extends INodeProcess {
/**
* The process.platform property returns a string identifying the operating system platform
* on which the Node.js process is running.
*/
readonly platform: 'win32' | 'linux' | 'darwin';
readonly platform: string;
/**
* The process.arch property returns a string identifying the CPU architecture
@@ -24,9 +24,14 @@ export interface IPartialNodeProcess {
readonly arch: string;
/**
* The type will always be Electron renderer.
* The type will always be `renderer`.
*/
readonly type: 'renderer';
readonly type: string;
/**
* Whether the process is sandboxed or not.
*/
readonly sandboxed: boolean;
/**
* A list of versions for the current node.js/electron configuration.
@@ -48,6 +53,11 @@ export interface IPartialNodeProcess {
*/
on: (type: string, callback: Function) => void;
/**
* The current working directory of the process.
*/
cwd: () => string;
/**
* Resolves with a ProcessMemoryInfo
*
@@ -62,9 +72,6 @@ export interface IPartialNodeProcess {
* process on macOS.
*/
getProcessMemoryInfo: () => Promise<ProcessMemoryInfo>;
}
export interface ISandboxNodeProcess extends IPartialNodeProcess {
/**
* A custom method we add to `process`: Resolve the true process environment to use and
@@ -84,14 +91,12 @@ export interface ISandboxNodeProcess extends IPartialNodeProcess {
* set of environment in `process.env`.
*/
resolveEnv(userEnv: IProcessEnvironment): Promise<void>;
}
export interface ISandboxContext {
/**
* Whether the renderer runs with `sandbox` enabled or not.
* Returns a process environment that includes any shell environment even if the application
* was not started from a shell / terminal / console.
*/
sandbox: boolean;
getShellEnv(): Promise<IProcessEnvironment>;
}
export interface IpcMessagePort {
@@ -114,4 +119,3 @@ export const ipcMessagePort: IpcMessagePort = globals.vscode.ipcMessagePort;
export const webFrame: WebFrame = globals.vscode.webFrame;
export const crashReporter: CrashReporter = globals.vscode.crashReporter;
export const process: ISandboxNodeProcess = globals.vscode.process;
export const context: ISandboxContext = globals.vscode.context;

View File

@@ -8,7 +8,7 @@ import { ipcRenderer, crashReporter, webFrame, process } from 'vs/base/parts/san
suite('Sandbox', () => {
test('globals', () => {
assert.ok(typeof ipcRenderer.invoke === 'function');
assert.ok(typeof ipcRenderer.send === 'function');
assert.ok(typeof crashReporter.addExtraParameter === 'function');
assert.ok(typeof webFrame.setZoomLevel === 'function');
assert.ok(typeof process.platform === 'string');

View File

@@ -49,80 +49,6 @@ suite('Arrays', () => {
assertMedian(13, [13, 4, 8], 2);
});
test('stableSort', () => {
function fill<T>(num: number, valueFn: () => T, arr: T[] = []): T[] {
for (let i = 0; i < num; i++) {
arr[i] = valueFn();
}
return arr;
}
let counter = 0;
let data = fill(10000, () => ({ n: 1, m: counter++ }));
arrays.mergeSort(data, (a, b) => a.n - b.n);
let lastM = -1;
for (const element of data) {
assert.ok(lastM < element.m);
lastM = element.m;
}
});
test('mergeSort', () => {
let data = arrays.mergeSort([6, 5, 3, 1, 8, 7, 2, 4], (a, b) => a - b);
assert.deepStrictEqual(data, [1, 2, 3, 4, 5, 6, 7, 8]);
});
test('mergeSort, sorted array', function () {
let data = arrays.mergeSort([1, 2, 3, 4, 5, 6], (a, b) => a - b);
assert.deepStrictEqual(data, [1, 2, 3, 4, 5, 6]);
});
test('mergeSort, is stable', function () {
let numbers = arrays.mergeSort([33, 22, 11, 4, 99, 1], (a, b) => 0);
assert.deepStrictEqual(numbers, [33, 22, 11, 4, 99, 1]);
});
test('mergeSort, many random numbers', function () {
function compare(a: number, b: number) {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
}
function assertSorted(array: number[]) {
let last = array[0];
for (let i = 1; i < array.length; i++) {
let n = array[i];
if (last > n) {
assert.fail(JSON.stringify(array.slice(i - 10, i + 10)));
}
}
}
const MAX = 101;
const data: number[][] = [];
for (let i = 1; i < MAX; i++) {
let array: number[] = [];
for (let j = 0; j < 10 + i; j++) {
array.push(Math.random() * 10e8 | 0);
}
data.push(array);
}
for (const array of data) {
arrays.mergeSort(array, compare);
assertSorted(array);
}
});
test('sortedDiff', () => {
function compare(a: number, b: number): number {
return a - b;

View File

@@ -88,7 +88,8 @@ suite('Buffer', () => {
await timeout(0);
stream.write(VSBuffer.fromString('Hello'));
await timeout(0);
stream.end(new Error());
stream.error(new Error());
stream.end();
assert.strictEqual(chunks.length, 1);
assert.strictEqual(chunks[0].toString(), 'Hello');
@@ -329,7 +330,8 @@ suite('Buffer', () => {
await timeout(0);
stream.write(VSBuffer.fromString('Hello'));
await timeout(0);
stream.end(new Error());
stream.error(new Error());
stream.end();
assert.strictEqual(chunks.length, 0);
assert.strictEqual(ended, false);

View File

@@ -66,6 +66,10 @@ suite('Stream', () => {
stream.error(new Error());
assert.strictEqual(error, true);
error = false;
stream.error(new Error());
assert.strictEqual(error, true);
stream.end('Final Bit');
assert.strictEqual(chunks.length, 4);
assert.strictEqual(chunks[3], 'Final Bit');
@@ -86,6 +90,15 @@ suite('Stream', () => {
assert.strictEqual(result, '');
});
test('WriteableStream - end with error works', async () => {
const reducer = (errors: Error[]) => errors.length > 0 ? errors[0] : null as unknown as Error;
const stream = newWriteableStream<Error>(reducer);
stream.end(new Error('error'));
const result = await consumeStream(stream, reducer);
assert.ok(result instanceof Error);
});
test('WriteableStream - removeListener', () => {
const stream = newWriteableStream<string>(strings => strings.join());

View File

@@ -28,3 +28,14 @@ export function testRepeat(n: number, description: string, callback: (this: any)
test(`${description} (iteration ${i})`, callback);
}
}
export async function assertThrowsAsync(block: () => any, message: string | Error = 'Missing expected exception'): Promise<void> {
try {
await block();
} catch {
return;
}
const err = message instanceof Error ? message : new Error(message);
throw err;
}

View File

@@ -8,9 +8,9 @@ import { join } from 'vs/base/common/path';
import { tmpdir } from 'os';
import { promises } from 'fs';
import { rimraf, writeFile } from 'vs/base/node/pfs';
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils';
suite('Crypto', () => {
flakySuite('Crypto', () => {
let testDir: string;

View File

@@ -10,10 +10,9 @@ import { join, sep } from 'vs/base/common/path';
import { generateUuid } from 'vs/base/common/uuid';
import { copy, exists, move, readdir, readDirsInDir, rimraf, RimRafMode, rimrafSync, SymlinkSupport, writeFile, writeFileSync } from 'vs/base/node/pfs';
import { timeout } from 'vs/base/common/async';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { canNormalize } from 'vs/base/common/normalization';
import { VSBuffer } from 'vs/base/common/buffer';
import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils';
import { flakySuite, getRandomTestPath, getPathFromAmdModule } from 'vs/base/test/node/testUtils';
import { isWindows } from 'vs/base/common/platform';
flakySuite('PFS', function () {
@@ -232,14 +231,19 @@ flakySuite('PFS', function () {
assert.ok(!symbolicLink2);
}
// Copy ignores dangling symlinks
// Copy does not fail over dangling symlinks
await rimraf(copyTarget);
await rimraf(symbolicLinkTarget);
await copy(symLink, copyTarget, { preserveSymlinks: true }); // this should not throw
assert.ok(!fs.existsSync(copyTarget));
if (!isWindows) {
const { symbolicLink } = await SymlinkSupport.stat(copyTarget);
assert.ok(symbolicLink?.dangling);
} else {
assert.ok(!fs.existsSync(copyTarget));
}
});
test('copy handles symbolic links when the reference is inside source', async () => {

View File

@@ -8,7 +8,7 @@ import * as cp from 'child_process';
import * as objects from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import * as processes from 'vs/base/node/processes';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { getPathFromAmdModule } from 'vs/base/test/node/testUtils';
function fork(id: string): cp.ChildProcess {
const opts: any = {

View File

@@ -5,12 +5,17 @@
import type { Suite } from 'mocha';
import { join } from 'vs/base/common/path';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
export function getRandomTestPath(tmpdir: string, ...segments: string[]): string {
return join(tmpdir, ...segments, generateUuid());
}
export function getPathFromAmdModule(requirefn: typeof require, relativePath: string): string {
return URI.parse(requirefn.toUrl(relativePath)).fsPath;
}
export function flakySuite(title: string, fn: (this: Suite) => void): Suite {
return suite(title, function () {

View File

@@ -6,7 +6,7 @@
import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { readFileSync } from 'fs';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { getPathFromAmdModule } from 'vs/base/test/node/testUtils';
suite('URI - perf', function () {

View File

@@ -9,9 +9,8 @@ import { tmpdir } from 'os';
import { promises } from 'fs';
import { extract } from 'vs/base/node/zip';
import { rimraf, exists } from 'vs/base/node/pfs';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { createCancelablePromise } from 'vs/base/common/async';
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
import { getRandomTestPath, getPathFromAmdModule } from 'vs/base/test/node/testUtils';
suite('Zip', () => {

View File

@@ -31,23 +31,15 @@ function getWorker(workerId: string, label: string): Worker | Promise<Worker> {
}
// ESM-comment-begin
export function getWorkerBootstrapUrl(scriptPath: string, label: string, forceDataUri: boolean = false): string {
if (forceDataUri || /^((http:)|(https:)|(file:))/.test(scriptPath)) {
const currentUrl = String(window.location);
const currentOrigin = currentUrl.substr(0, currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length);
if (forceDataUri || scriptPath.substring(0, currentOrigin.length) !== currentOrigin) {
// this is the cross-origin case
// i.e. the webpage is running at a different origin than where the scripts are loaded from
const myPath = 'vs/base/worker/defaultWorkerFactory.js';
const workerBaseUrl = require.toUrl(myPath).slice(0, -myPath.length); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
const js = `/*${label}*/self.MonacoEnvironment={baseUrl: '${workerBaseUrl}'};importScripts('${scriptPath}');/*${label}*/`;
if (forceDataUri) {
const url = `data:text/javascript;charset=utf-8,${encodeURIComponent(js)}`;
return url;
}
const blob = new Blob([js], { type: 'application/javascript' });
return URL.createObjectURL(blob);
}
export function getWorkerBootstrapUrl(scriptPath: string, label: string): string {
if (/^((http:)|(https:)|(file:))/.test(scriptPath) && scriptPath.substring(0, self.origin.length) !== self.origin) {
// this is the cross-origin case
// i.e. the webpage is running at a different origin than where the scripts are loaded from
const myPath = 'vs/base/worker/defaultWorkerFactory.js';
const workerBaseUrl = require.toUrl(myPath).slice(0, -myPath.length); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
const js = `/*${label}*/self.MonacoEnvironment={baseUrl: '${workerBaseUrl}'};importScripts('${scriptPath}');/*${label}*/`;
const blob = new Blob([js], { type: 'application/javascript' });
return URL.createObjectURL(blob);
}
return scriptPath + '#' + label;
}

View File

@@ -10,36 +10,77 @@
const trustedTypesPolicy = (
typeof self.trustedTypes?.createPolicy === 'function'
? self.trustedTypes?.createPolicy('amdLoader', { createScriptURL: value => value })
? self.trustedTypes?.createPolicy('amdLoader', {
createScriptURL: value => value,
createScript: (_, ...args: string[]) => {
// workaround a chrome issue not allowing to create new functions
// see https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor
const fnArgs = args.slice(0, -1).join(',');
const fnBody = args.pop()!.toString();
const body = `(function anonymous(${fnArgs}) {\n${fnBody}\n})`;
return body;
}
})
: undefined
);
if (typeof (<any>self).define !== 'function' || !(<any>self).define.amd) {
let loaderSrc: string | TrustedScriptURL = monacoBaseUrl + 'vs/loader.js';
if (trustedTypesPolicy) {
loaderSrc = trustedTypesPolicy.createScriptURL(loaderSrc);
}
importScripts(loaderSrc as string);
function loadAMDLoader() {
return new Promise<void>((resolve, reject) => {
if (typeof (<any>self).define === 'function' && (<any>self).define.amd) {
return resolve();
}
const loaderSrc: string | TrustedScriptURL = monacoBaseUrl + 'vs/loader.js';
const isCrossOrigin = (/^((http:)|(https:)|(file:))/.test(loaderSrc) && loaderSrc.substring(0, self.origin.length) !== self.origin);
if (!isCrossOrigin) {
// use `fetch` if possible because `importScripts`
// is synchronous and can lead to deadlocks on Safari
fetch(loaderSrc).then((response) => {
if (response.status !== 200) {
throw new Error(response.statusText);
}
return response.text();
}).then((text) => {
text = `${text}\n//# sourceURL=${loaderSrc}`;
const func = (
trustedTypesPolicy
? self.eval(trustedTypesPolicy.createScript('', text) as unknown as string)
: new Function(text)
);
func.call(self);
resolve();
}).then(undefined, reject);
return;
}
if (trustedTypesPolicy) {
importScripts(trustedTypesPolicy.createScriptURL(loaderSrc) as unknown as string);
} else {
importScripts(loaderSrc as string);
}
resolve();
});
}
require.config({
baseUrl: monacoBaseUrl,
catchError: true,
trustedTypesPolicy,
});
const loadCode = function (moduleId: string) {
loadAMDLoader().then(() => {
require.config({
baseUrl: monacoBaseUrl,
catchError: true,
trustedTypesPolicy,
});
require([moduleId], function (ws) {
setTimeout(function () {
let messageHandler = ws.create((msg: any, transfer?: Transferable[]) => {
(<any>self).postMessage(msg, transfer);
}, null);
let loadCode = function (moduleId: string) {
require([moduleId], function (ws) {
setTimeout(function () {
let messageHandler = ws.create((msg: any, transfer?: Transferable[]) => {
(<any>self).postMessage(msg, transfer);
}, null);
self.onmessage = (e: MessageEvent) => messageHandler.onmessage(e.data);
while (beforeReadyMessages.length > 0) {
self.onmessage(beforeReadyMessages.shift()!);
}
}, 0);
self.onmessage = (e: MessageEvent) => messageHandler.onmessage(e.data);
while (beforeReadyMessages.length > 0) {
self.onmessage(beforeReadyMessages.shift()!);
}
}, 0);
});
});
};

View File

@@ -0,0 +1,80 @@
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<script>
performance.mark('code/didStartRenderer')
</script>
<meta charset="utf-8" />
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<!-- Workbench Configuration -->
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONFIGURATION}}">
<!-- Workbench Auth Session -->
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
<!-- Workbench Icon/Manifest/CSS -->
<link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/manifest.json">
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.api.css">
</head>
<body aria-label="">
</body>
<!-- Startup (do not modify order of script tags!) -->
<script>
var baseUrl = '{{WORKBENCH_WEB_BASE_URL}}';
self.require = {
baseUrl: `${baseUrl}/out`,
recordStats: true,
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
createScriptURL(value) {
if(value.startsWith(baseUrl)) {
return value;
}
throw new Error(`Invalid script url: ${value}`)
}
}),
paths: {
'vscode-textmate': `${baseUrl}/node_modules/vscode-textmate/release/main`,
'vscode-oniguruma': `${baseUrl}/node_modules/vscode-oniguruma/release/main`,
'xterm': `${baseUrl}/node_modules/xterm/lib/xterm.js`,
'xterm-addon-search': `${baseUrl}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`,
'xterm-addon-unicode11': `${baseUrl}/node_modules/xterm-addon-unicode11/lib/xterm-addon-unicode11.js`,
'xterm-addon-webgl': `${baseUrl}/node_modules/xterm-addon-webgl/lib/xterm-addon-webgl.js`,
'tas-client-umd': `${baseUrl}/node_modules/tas-client-umd/lib/tas-client-umd.js`,
'iconv-lite-umd': `${baseUrl}/node_modules/iconv-lite-umd/lib/iconv-lite-umd.js`,
'jschardet': `${baseUrl}/node_modules/jschardet/dist/jschardet.min.js`,
}
};
</script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/loader.js"></script>
<script>
performance.mark('code/willLoadWorkbenchMain');
</script>
<script>
if ("{{WORKBENCH_DEV}}" === "true") {
const workbench = document.createElement('script');
workbench.innerText = "require(['vs/code/browser/workbench/workbench'], function() {});";
document.body.appendChild(workbench);
} else {
const nls = document.createElement('script');
nls.setAttribute('src', '{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.api.nls.js');
document.body.appendChild(nls);
const api = document.createElement('script');
api.setAttribute('src', '{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.api.js');
document.body.appendChild(api);
const workbench = document.createElement('script');
workbench.setAttribute('src', '{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.js');
document.body.appendChild(workbench);
}
</script>
</html>

View File

@@ -7,7 +7,7 @@ import * as fs from 'fs';
import * as path from 'vs/base/common/path';
import * as pfs from 'vs/base/node/pfs';
import { IStringDictionary } from 'vs/base/common/collections';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ILogService } from 'vs/platform/log/common/log';
@@ -32,9 +32,14 @@ interface LanguagePackFile {
export class LanguagePackCachedDataCleaner extends Disposable {
private readonly _DataMaxAge = this._productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
constructor(
@INativeEnvironmentService private readonly _environmentService: INativeEnvironmentService,
@ILogService private readonly _logService: ILogService
@ILogService private readonly _logService: ILogService,
@IProductService private readonly _productService: IProductService
) {
super();
// We have no Language pack support for dev version (run from source)
@@ -48,9 +53,6 @@ export class LanguagePackCachedDataCleaner extends Disposable {
let handle: any = setTimeout(async () => {
handle = undefined;
this._logService.info('Starting to clean up unused language packs.');
const maxAge = product.nameLong.indexOf('Insiders') >= 0
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
try {
const installed: IStringDictionary<boolean> = Object.create(null);
const metaData: LanguagePackFile = JSON.parse(await fs.promises.readFile(path.join(this._environmentService.userDataPath, 'languagepacks.json'), 'utf8'));
@@ -84,7 +86,7 @@ export class LanguagePackCachedDataCleaner extends Disposable {
const stat = await fs.promises.stat(candidate);
if (stat.isDirectory()) {
const diff = now - stat.mtime.getTime();
if (diff > maxAge) {
if (diff > this._DataMaxAge) {
this._logService.info('Removing language pack cache entry: ', path.join(packEntry, entry));
await pfs.rimraf(candidate);
}

View File

@@ -8,18 +8,19 @@ import { basename, dirname, join } from 'vs/base/common/path';
import { onUnexpectedError } from 'vs/base/common/errors';
import { toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { readdir, rimraf } from 'vs/base/node/pfs';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
export class NodeCachedDataCleaner {
private static readonly _DataMaxAge = product.nameLong.indexOf('Insiders') >= 0
private readonly _DataMaxAge = this.productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
private readonly _disposables = new DisposableStore();
constructor(
private readonly nodeCachedDataDir: string | undefined
private readonly nodeCachedDataDir: string | undefined,
@IProductService private readonly productService: IProductService
) {
this._manageCachedDataSoon();
}
@@ -61,7 +62,7 @@ export class NodeCachedDataCleaner {
// * only when old enough
if (stats.isDirectory()) {
const diff = now - stats.mtime.getTime();
if (diff > NodeCachedDataCleaner._DataMaxAge) {
if (diff > this._DataMaxAge) {
return rimraf(path);
}
}

View File

@@ -13,7 +13,7 @@ import { StaticRouter, ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
import { ExtensionManagementChannel, ExtensionTipsChannel } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
import { IExtensionManagementService, IExtensionGalleryService, IGlobalExtensionEnablementService, IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement';
@@ -23,7 +23,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
import { IRequestService } from 'vs/platform/request/common/request';
import { RequestService } from 'vs/platform/request/browser/requestService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ICustomEndpointTelemetryService, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { combinedAppender, NullTelemetryService, ITelemetryAppender, NullAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetryIpc';
@@ -58,7 +58,7 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
import { LoggerService } from 'vs/platform/log/node/loggerService';
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
import { UserDataAutoSyncService } from 'vs/platform/userDataSync/electron-sandbox/userDataAutoSyncService';
import { NativeStorageService2 } from 'vs/platform/storage/electron-sandbox/storageService2';
import { NativeStorageService } from 'vs/platform/storage/electron-sandbox/storageService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
import { UserDataSyncResourceEnablementService } from 'vs/platform/userDataSync/common/userDataSyncResourceEnablementService';
@@ -81,9 +81,12 @@ import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/err
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { join } from 'vs/base/common/path';
import { TerminalIpcChannels } from 'vs/platform/terminal/common/terminal';
import { LocalPtyService } from 'vs/platform/terminal/electron-browser/localPtyService';
import { PtyHostService } from 'vs/platform/terminal/node/ptyHostService';
import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal';
import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncServiceIpc';
import { IChecksumService } from 'vs/platform/checksum/common/checksumService';
import { ChecksumService } from 'vs/platform/checksum/node/checksumService';
import { CustomEndpointTelemetryService } from 'vs/platform/telemetry/node/customEndpointTelemetryService';
class SharedProcessMain extends Disposable {
@@ -129,7 +132,7 @@ class SharedProcessMain extends Disposable {
// Instantiate Contributions
this._register(combinedDisposable(
new NodeCachedDataCleaner(this.configuration.nodeCachedDataDir),
instantiationService.createInstance(NodeCachedDataCleaner, this.configuration.nodeCachedDataDir),
instantiationService.createInstance(LanguagePackCachedDataCleaner),
instantiationService.createInstance(StorageDataCleaner, this.configuration.backupWorkspacesPath),
instantiationService.createInstance(LogsDataCleaner),
@@ -141,9 +144,12 @@ class SharedProcessMain extends Disposable {
private async initServices(): Promise<IInstantiationService> {
const services = new ServiceCollection();
// Product
const productService = { _serviceBrand: undefined, ...product };
services.set(IProductService, productService);
// Environment
const environmentService = new NativeEnvironmentService(this.configuration.args);
services.set(IEnvironmentService, environmentService);
const environmentService = new NativeEnvironmentService(this.configuration.args, productService);
services.set(INativeEnvironmentService, environmentService);
// Log
@@ -175,18 +181,18 @@ class SharedProcessMain extends Disposable {
await configurationService.initialize();
// Storage (global access only)
const storageService = new NativeStorageService2(undefined, mainProcessService, environmentService);
const storageService = new NativeStorageService(undefined, mainProcessService, environmentService);
services.set(IStorageService, storageService);
await storageService.initialize();
this._register(toDisposable(() => storageService.flush()));
// Product
services.set(IProductService, { _serviceBrand: undefined, ...product });
// Request
services.set(IRequestService, new SyncDescriptor(RequestService));
// Checksum
services.set(IChecksumService, new SyncDescriptor(ChecksumService));
// Native Host
const nativeHostService = ProxyChannel.toService<INativeHostService>(mainProcessService.getChannel('nativeHost'), { context: this.configuration.windowId });
services.set(INativeHostService, nativeHostService);
@@ -208,19 +214,19 @@ class SharedProcessMain extends Disposable {
let telemetryService: ITelemetryService;
let telemetryAppender: ITelemetryAppender;
if (!extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) {
if (!extensionDevelopmentLocationURI && !environmentService.disableTelemetry && productService.enableTelemetry) {
telemetryAppender = new TelemetryLogAppender(loggerService, environmentService);
// Application Insights
if (product.aiConfig && product.aiConfig.asimovKey && isBuilt) {
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, product.aiConfig.asimovKey);
if (productService.aiConfig && productService.aiConfig.asimovKey && isBuilt) {
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey);
this._register(toDisposable(() => appInsightsAppender.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
telemetryAppender = combinedAppender(appInsightsAppender, telemetryAppender);
}
telemetryService = new TelemetryService({
appender: telemetryAppender,
commonProperties: resolveCommonProperties(fileService, release(), process.arch, product.commit, product.version, this.configuration.machineId, product.msftInternalDomains, installSourcePath),
commonProperties: resolveCommonProperties(fileService, release(), process.arch, productService.commit, productService.version, this.configuration.machineId, productService.msftInternalDomains, installSourcePath),
sendErrorTelemetry: true,
piiPaths: [appRoot, extensionsPath]
}, configurationService);
@@ -232,6 +238,10 @@ class SharedProcessMain extends Disposable {
this.server.registerChannel('telemetryAppender', new TelemetryAppenderChannel(telemetryAppender));
services.set(ITelemetryService, telemetryService);
// Custom Endpoint Telemetry
const customEndpointTelemetryService = new CustomEndpointTelemetryService(configurationService, telemetryService);
services.set(ICustomEndpointTelemetryService, customEndpointTelemetryService);
// Extension Management
services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService));
@@ -263,8 +273,7 @@ class SharedProcessMain extends Disposable {
services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService));
// Terminal
const localPtyService = this._register(new LocalPtyService(logService));
services.set(ILocalPtyService, localPtyService);
services.set(ILocalPtyService, this._register(new PtyHostService(logService)));
return new InstantiationService(services);
}
@@ -287,10 +296,18 @@ class SharedProcessMain extends Disposable {
const extensionTipsChannel = new ExtensionTipsChannel(accessor.get(IExtensionTipsService));
this.server.registerChannel('extensionTipsService', extensionTipsChannel);
// Checksum
const checksumChannel = ProxyChannel.fromService(accessor.get(IChecksumService));
this.server.registerChannel('checksum', checksumChannel);
// Settings Sync
const userDataSyncMachineChannel = new UserDataSyncMachinesServiceChannel(accessor.get(IUserDataSyncMachinesService));
this.server.registerChannel('userDataSyncMachines', userDataSyncMachineChannel);
// Custom Endpoint Telemetry
const customEndpointTelemetryChannel = ProxyChannel.fromService(accessor.get(ICustomEndpointTelemetryService));
this.server.registerChannel('customEndpointTelemetry', customEndpointTelemetryChannel);
const userDataSyncAccountChannel = new UserDataSyncAccountServiceChannel(accessor.get(IUserDataSyncAccountService));
this.server.registerChannel('userDataSyncAccount', userDataSyncAccountChannel);

View File

@@ -33,7 +33,7 @@ import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtil
import { TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
import { FileProtocolHandler } from 'vs/code/electron-main/protocol';
import { Disposable } from 'vs/base/common/lifecycle';
@@ -80,13 +80,14 @@ import { EncryptionMainService, IEncryptionMainService } from 'vs/platform/encry
import { ActiveWindowManager } from 'vs/platform/windows/node/windowTracker';
import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/electron-main/displayMainService';
import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper';
import { isEqualOrParent } from 'vs/base/common/extpath';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust';
import { ExtensionUrlTrustService } from 'vs/platform/extensionManagement/node/extensionUrlTrustService';
import { once } from 'vs/base/common/functional';
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
import { ISignService } from 'vs/platform/sign/common/sign';
/**
* The main VS Code application. There will only ever be one instance,
@@ -105,7 +106,8 @@ export class CodeApplication extends Disposable {
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IStateService private readonly stateService: IStateService,
@IFileService private readonly fileService: IFileService
@IFileService private readonly fileService: IFileService,
@IProductService private readonly productService: IProductService
) {
super();
@@ -418,7 +420,7 @@ export class CodeApplication extends Disposable {
// This will help Windows to associate the running program with
// any shortcut that is pinned to the taskbar and prevent showing
// two icons in the taskbar for the same app.
const win32AppUserModelId = product.win32AppUserModelId;
const win32AppUserModelId = this.productService.win32AppUserModelId;
if (isWindows && win32AppUserModelId) {
app.setAppUserModelId(win32AppUserModelId);
}
@@ -559,9 +561,6 @@ export class CodeApplication extends Disposable {
// Keyboard Layout
services.set(IKeyboardLayoutMainService, new SyncDescriptor(KeyboardLayoutMainService));
// Display
services.set(IDisplayMainService, new SyncDescriptor(DisplayMainService));
// Native Host
services.set(INativeHostMainService, new SyncDescriptor(NativeHostMainService, [sharedProcess]));
@@ -590,10 +589,10 @@ export class CodeApplication extends Disposable {
services.set(IURLService, new SyncDescriptor(NativeURLService));
// Telemetry
if (!this.environmentMainService.isExtensionDevelopment && !this.environmentMainService.args['disable-telemetry'] && !!product.enableTelemetry) {
if (!this.environmentMainService.isExtensionDevelopment && !this.environmentMainService.args['disable-telemetry'] && !!this.productService.enableTelemetry) {
const channel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('telemetryAppender')));
const appender = new TelemetryAppenderClient(channel);
const commonProperties = resolveCommonProperties(this.fileService, release(), process.arch, product.commit, product.version, machineId, product.msftInternalDomains, this.environmentMainService.installSourcePath);
const commonProperties = resolveCommonProperties(this.fileService, release(), process.arch, this.productService.commit, this.productService.version, machineId, this.productService.msftInternalDomains, this.environmentMainService.installSourcePath);
const piiPaths = [this.environmentMainService.appRoot, this.environmentMainService.extensionsPath];
const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths, sendErrorTelemetry: true };
@@ -629,14 +628,14 @@ export class CodeApplication extends Disposable {
const encryptionChannel = ProxyChannel.fromService(accessor.get(IEncryptionMainService));
mainProcessElectronServer.registerChannel('encryption', encryptionChannel);
// Signing
const signChannel = ProxyChannel.fromService(accessor.get(ISignService));
mainProcessElectronServer.registerChannel('sign', signChannel);
// Keyboard Layout
const keyboardLayoutChannel = ProxyChannel.fromService(accessor.get(IKeyboardLayoutMainService));
mainProcessElectronServer.registerChannel('keyboardLayout', keyboardLayoutChannel);
// Display
const displayChannel = ProxyChannel.fromService(accessor.get(IDisplayMainService));
mainProcessElectronServer.registerChannel('display', displayChannel);
// Native host (main & shared process)
this.nativeHostMainService = accessor.get(INativeHostMainService);
const nativeHostChannel = ProxyChannel.fromService(this.nativeHostMainService);
@@ -751,6 +750,7 @@ export class CodeApplication extends Disposable {
cli: { ...environmentService.args },
urisToOpen: [windowOpenableFromProtocolLink],
gotoLineMode: true
/* remoteAuthority will be determined based on windowOpenableFromProtocolLink */
});
window.focus(); // this should help ensuring that the right window gets focus when multiple are opened
@@ -765,7 +765,8 @@ export class CodeApplication extends Disposable {
context: OpenContext.API,
cli: { ...environmentService.args },
forceEmpty: true,
gotoLineMode: true
gotoLineMode: true,
remoteAuthority: getRemoteAuthority(uri)
});
await window.ready();
@@ -789,7 +790,7 @@ export class CodeApplication extends Disposable {
urlService.registerHandler(new URLHandlerChannelClient(urlHandlerChannel));
// Watch Electron URLs and forward them to the UrlService
this._register(new ElectronURLListener(pendingProtocolLinksToHandle, urlService, windowsMainService, this.environmentMainService));
this._register(new ElectronURLListener(pendingProtocolLinksToHandle, urlService, windowsMainService, this.environmentMainService, this.productService));
// Open our first window
const args = this.environmentMainService.args;
@@ -800,6 +801,7 @@ export class CodeApplication extends Disposable {
const hasFileURIs = !!args['file-uri'];
const noRecentEntry = args['skip-add-to-recently-opened'] === true;
const waitMarkerFileURI = args.wait && args.waitMarkerFilePath ? URI.file(args.waitMarkerFilePath) : undefined;
const remoteAuthority = args.remote || undefined;
// check for a pending window to open from URI
// e.g. when running code with --open-uri from
@@ -811,6 +813,7 @@ export class CodeApplication extends Disposable {
urisToOpen: pendingWindowOpenablesFromProtocolLinks,
gotoLineMode: true,
initialStartup: true
/* remoteAuthority will be determined based on pendingWindowOpenablesFromProtocolLinks */
});
}
@@ -823,7 +826,8 @@ export class CodeApplication extends Disposable {
forceEmpty: true,
noRecentEntry,
waitMarkerFileURI,
initialStartup: true
initialStartup: true,
remoteAuthority
});
}
@@ -835,7 +839,8 @@ export class CodeApplication extends Disposable {
urisToOpen: macOpenFiles.map(file => this.getWindowOpenableFromPathSync(file)),
noRecentEntry,
waitMarkerFileURI,
initialStartup: true
initialStartup: true,
/* remoteAuthority will be determined based on macOpenFiles */
});
}
@@ -848,21 +853,22 @@ export class CodeApplication extends Disposable {
noRecentEntry,
waitMarkerFileURI,
gotoLineMode: args.goto,
initialStartup: true
initialStartup: true,
remoteAuthority
});
}
private shouldBlockURI(uri: URI): boolean {
if (uri.authority === Schemas.file && isWindows) {
const res = dialog.showMessageBoxSync({
title: product.nameLong,
title: this.productService.nameLong,
type: 'question',
buttons: [
mnemonicButtonLabel(localize({ key: 'open', comment: ['&& denotes a mnemonic'] }, "&&Yes")),
mnemonicButtonLabel(localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&No")),
],
cancelId: 1,
message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath, this.environmentMainService), product.nameShort),
message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath, this.environmentMainService), this.productService.nameShort),
detail: localize('confirmOpenDetail', "If you did not initiate this request, it may represent an attempted attack on your system. Unless you took an explicit action to initiate this request, you should press 'No'"),
noLink: true
});
@@ -948,16 +954,22 @@ export class CodeApplication extends Disposable {
type SharedProcessErrorClassification = {
type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
reason: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
visible: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
};
type SharedProcessErrorEvent = {
type: WindowError;
reason: string | undefined;
visible: boolean;
};
telemetryService.publicLog2<SharedProcessErrorEvent, SharedProcessErrorClassification>('sharedprocesserror', { type, reason: typeof details !== 'string' ? details.reason : undefined });
telemetryService.publicLog2<SharedProcessErrorEvent, SharedProcessErrorClassification>('sharedprocesserror', {
type,
reason: typeof details !== 'string' ? details?.reason : undefined,
visible: sharedProcess.isVisible()
});
}));
// Windows: install mutex
const win32MutexName = product.win32MutexName;
const win32MutexName = this.productService.win32MutexName;
if (isWindows && win32MutexName) {
try {
const WindowsMutex = (require.__$__nodeRequire('windows-mutex') as typeof import('windows-mutex')).Mutex;
@@ -1027,7 +1039,7 @@ export class CodeApplication extends Disposable {
recordingStopped = true; // only once
const path = await contentTracing.stopRecording(joinPath(this.environmentMainService.userHome, `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`).fsPath);
const path = await contentTracing.stopRecording(joinPath(this.environmentMainService.userHome, `${this.productService.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`).fsPath);
if (!timeout) {
dialogMainService.showMessageBox({

View File

@@ -12,7 +12,7 @@ import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { INativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService';
import { IEncryptionMainService } from 'vs/platform/encryption/electron-main/encryptionMainService';
import { generateUuid } from 'vs/base/common/uuid';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { CancellationToken } from 'vs/base/common/cancellation';
interface ElectronAuthenticationResponseDetails extends AuthenticationResponseDetails {
@@ -56,7 +56,7 @@ enum ProxyAuthState {
export class ProxyAuthHandler extends Disposable {
private static PROXY_CREDENTIALS_SERVICE_KEY = `${product.urlProtocol}.proxy-credentials`;
private readonly PROXY_CREDENTIALS_SERVICE_KEY = `${this.productService.urlProtocol}.proxy-credentials`;
private pendingProxyResolve: Promise<Credentials | undefined> | undefined = undefined;
@@ -68,7 +68,8 @@ export class ProxyAuthHandler extends Disposable {
@ILogService private readonly logService: ILogService,
@IWindowsMainService private readonly windowsMainService: IWindowsMainService,
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
@IEncryptionMainService private readonly encryptionMainService: IEncryptionMainService
@IEncryptionMainService private readonly encryptionMainService: IEncryptionMainService,
@IProductService private readonly productService: IProductService
) {
super();
@@ -153,7 +154,7 @@ export class ProxyAuthHandler extends Disposable {
let storedUsername: string | undefined = undefined;
let storedPassword: string | undefined = undefined;
try {
const encryptedSerializedProxyCredentials = await this.nativeHostMainService.getPassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
const encryptedSerializedProxyCredentials = await this.nativeHostMainService.getPassword(undefined, this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
if (encryptedSerializedProxyCredentials) {
const credentials: Credentials = JSON.parse(await this.encryptionMainService.decrypt(encryptedSerializedProxyCredentials));
@@ -211,9 +212,9 @@ export class ProxyAuthHandler extends Disposable {
try {
if (reply.remember) {
const encryptedSerializedCredentials = await this.encryptionMainService.encrypt(JSON.stringify(credentials));
await this.nativeHostMainService.setPassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash, encryptedSerializedCredentials);
await this.nativeHostMainService.setPassword(undefined, this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash, encryptedSerializedCredentials);
} else {
await this.nativeHostMainService.deletePassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
await this.nativeHostMainService.deletePassword(undefined, this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
}
} catch (error) {
this.logService.error(error); // handle gracefully

View File

@@ -23,7 +23,6 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ILogService, ConsoleMainLogger, MultiplexLogService, getLogLevel, ILoggerService } from 'vs/platform/log/common/log';
import { StateService } from 'vs/platform/state/node/stateService';
import { IStateService } from 'vs/platform/state/node/state';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
@@ -54,6 +53,7 @@ import { EnvironmentMainService, IEnvironmentMainService } from 'vs/platform/env
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { LoggerService } from 'vs/platform/log/node/loggerService';
import { cwd } from 'vs/base/common/process';
/**
* The main VS Code entry point.
@@ -84,7 +84,7 @@ class CodeMain {
const args = this.resolveArgs();
// Create services
const [instantiationService, instanceEnvironment, environmentService, configurationService, stateService, bufferLogService] = this.createServices(args);
const [instantiationService, instanceEnvironment, environmentService, configurationService, stateService, bufferLogService, productService] = this.createServices(args);
try {
@@ -94,7 +94,7 @@ class CodeMain {
} catch (error) {
// Show a dialog for errors that can be resolved by the user
this.handleStartupDataDirError(environmentService, error);
this.handleStartupDataDirError(environmentService, productService.nameLong, error);
throw error;
}
@@ -108,7 +108,7 @@ class CodeMain {
// Create the main IPC server by trying to be the server
// If this throws an error it means we are not the first
// instance of VS Code running and so we would quit.
const mainProcessNodeIpcServer = await this.doStartup(args, logService, environmentService, lifecycleMainService, instantiationService, true);
const mainProcessNodeIpcServer = await this.doStartup(args, logService, environmentService, lifecycleMainService, instantiationService, productService, true);
// Delay creation of spdlog for perf reasons (https://github.com/microsoft/vscode/issues/72906)
bufferLogService.logger = new SpdLogLogger('main', join(environmentService.logsPath, 'main.log'), true, bufferLogService.getLevel());
@@ -126,20 +126,23 @@ class CodeMain {
}
}
private createServices(args: NativeParsedArgs): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateService, BufferLogService] {
private createServices(args: NativeParsedArgs): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateService, BufferLogService, IProductService] {
const services = new ServiceCollection();
// Product
const productService = { _serviceBrand: undefined, ...product };
services.set(IProductService, productService);
// Environment
const environmentService = new EnvironmentMainService(args);
const instanceEnvironment = this.patchEnvironment(environmentService); // Patch `process.env` with the instance's environment
services.set(IEnvironmentService, environmentService);
services.set(IEnvironmentMainService, environmentService);
const environmentMainService = new EnvironmentMainService(args, productService);
const instanceEnvironment = this.patchEnvironment(environmentMainService); // Patch `process.env` with the instance's environment
services.set(IEnvironmentMainService, environmentMainService);
// Log: We need to buffer the spdlog logs until we are sure
// we are the only instance running, otherwise we'll have concurrent
// log file access on Windows (https://github.com/microsoft/vscode/issues/41218)
const bufferLogService = new BufferLogService();
const logService = new MultiplexLogService([new ConsoleMainLogger(getLogLevel(environmentService)), bufferLogService]);
const logService = new MultiplexLogService([new ConsoleMainLogger(getLogLevel(environmentMainService)), bufferLogService]);
process.once('exit', () => logService.dispose());
services.set(ILogService, logService);
@@ -153,14 +156,14 @@ class CodeMain {
services.set(ILoggerService, new LoggerService(logService, fileService));
// Configuration
const configurationService = new ConfigurationService(environmentService.settingsResource, fileService);
const configurationService = new ConfigurationService(environmentMainService.settingsResource, fileService);
services.set(IConfigurationService, configurationService);
// Lifecycle
services.set(ILifecycleMainService, new SyncDescriptor(LifecycleMainService));
// State
const stateService = new StateService(environmentService, logService);
const stateService = new StateService(environmentMainService, logService);
services.set(IStateService, stateService);
// Request
@@ -172,13 +175,10 @@ class CodeMain {
// Signing
services.set(ISignService, new SyncDescriptor(SignService));
// Product
services.set(IProductService, { _serviceBrand: undefined, ...product });
// Tunnel
services.set(ITunnelService, new SyncDescriptor(TunnelService));
return [new InstantiationService(services, true), instanceEnvironment, environmentService, configurationService, stateService, bufferLogService];
return [new InstantiationService(services, true), instanceEnvironment, environmentMainService, configurationService, stateService, bufferLogService, productService];
}
private patchEnvironment(environmentMainService: IEnvironmentMainService): IProcessEnvironment {
@@ -219,7 +219,7 @@ class CodeMain {
return Promise.all([environmentServiceInitialization, configurationServiceInitialization, stateServiceInitialization]);
}
private async doStartup(args: NativeParsedArgs, logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, retry: boolean): Promise<NodeIPCServer> {
private async doStartup(args: NativeParsedArgs, logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, productService: IProductService, retry: boolean): Promise<NodeIPCServer> {
// Try to setup a server for running. If that succeeds it means
// we are the first instance to startup. Otherwise it is likely
@@ -235,7 +235,7 @@ class CodeMain {
if (error.code !== 'EADDRINUSE') {
// Show a dialog for errors that can be resolved by the user
this.handleStartupDataDirError(environmentMainService, error);
this.handleStartupDataDirError(environmentMainService, productService.nameLong, error);
// Any other runtime error is just printed to the console
throw error;
@@ -251,8 +251,9 @@ class CodeMain {
if (!retry || isWindows || error.code !== 'ECONNREFUSED') {
if (error.code === 'EPERM') {
this.showStartupWarningDialog(
localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", product.nameShort),
localize('secondInstanceAdminDetail', "Please close the other instance and try again.")
localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", productService.nameShort),
localize('secondInstanceAdminDetail', "Please close the other instance and try again."),
productService.nameLong
);
}
@@ -270,7 +271,7 @@ class CodeMain {
throw error;
}
return this.doStartup(args, logService, environmentMainService, lifecycleMainService, instantiationService, false);
return this.doStartup(args, logService, environmentMainService, lifecycleMainService, instantiationService, productService, false);
}
// Tests from CLI require to be the only instance currently
@@ -289,8 +290,9 @@ class CodeMain {
if (!args.wait && !args.status) {
startupWarningDialogHandle = setTimeout(() => {
this.showStartupWarningDialog(
localize('secondInstanceNoResponse', "Another instance of {0} is running but not responding", product.nameShort),
localize('secondInstanceNoResponseDetail', "Please close all other instances and try again.")
localize('secondInstanceNoResponse', "Another instance of {0} is running but not responding", productService.nameShort),
localize('secondInstanceNoResponseDetail', "Please close all other instances and try again."),
productService.nameLong
);
}, 10000);
}
@@ -300,7 +302,7 @@ class CodeMain {
// Process Info
if (args.status) {
return instantiationService.invokeFunction(async () => {
const diagnosticsService = new DiagnosticsService(NullTelemetryService);
const diagnosticsService = new DiagnosticsService(NullTelemetryService, productService);
const mainProcessInfo = await launchService.getMainProcessInfo();
const remoteDiagnostics = await launchService.getRemoteDiagnostics({ includeProcesses: true, includeWorkspaceMetadata: true });
const diagnostics = await diagnosticsService.getDiagnostics(mainProcessInfo, remoteDiagnostics);
@@ -344,23 +346,24 @@ class CodeMain {
return mainProcessNodeIpcServer;
}
private handleStartupDataDirError(environmentMainService: IEnvironmentMainService, error: NodeJS.ErrnoException): void {
private handleStartupDataDirError(environmentMainService: IEnvironmentMainService, title: string, error: NodeJS.ErrnoException): void {
if (error.code === 'EACCES' || error.code === 'EPERM') {
const directories = coalesce([environmentMainService.userDataPath, environmentMainService.extensionsPath, XDG_RUNTIME_DIR]).map(folder => getPathLabel(folder, environmentMainService));
this.showStartupWarningDialog(
localize('startupDataDirError', "Unable to write program user data."),
localize('startupUserDataAndExtensionsDirErrorDetail', "{0}\n\nPlease make sure the following directories are writeable:\n\n{1}", toErrorMessage(error), directories.join('\n'))
localize('startupUserDataAndExtensionsDirErrorDetail', "{0}\n\nPlease make sure the following directories are writeable:\n\n{1}", toErrorMessage(error), directories.join('\n')),
title
);
}
}
private showStartupWarningDialog(message: string, detail: string): void {
private showStartupWarningDialog(message: string, detail: string, title: string): void {
// use sync variant here because we likely exit after this method
// due to startup issues and otherwise the dialog seems to disappear
// https://github.com/microsoft/vscode/issues/104493
dialog.showMessageBoxSync({
title: product.nameLong,
title,
type: 'warning',
buttons: [mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message,
@@ -451,7 +454,7 @@ class CodeMain {
}
private doValidatePaths(args: string[], gotoLineMode?: boolean): string[] {
const cwd = process.env['VSCODE_CWD'] || process.cwd();
const currentWorkingDir = cwd();
const result = args.map(arg => {
let pathCandidate = String(arg);
@@ -462,10 +465,10 @@ class CodeMain {
}
if (pathCandidate) {
pathCandidate = this.preparePath(cwd, pathCandidate);
pathCandidate = this.preparePath(currentWorkingDir, pathCandidate);
}
const sanitizedFilePath = sanitizeFilePath(pathCandidate, cwd);
const sanitizedFilePath = sanitizeFilePath(pathCandidate, currentWorkingDir);
const filePathBasename = basename(sanitizedFilePath);
if (filePathBasename /* can be empty if code is opened on root */ && !isValidBasename(filePathBasename)) {

View File

@@ -13,12 +13,14 @@ import { ILogService } from 'vs/platform/log/common/log';
import { TernarySearchTree } from 'vs/base/common/map';
import { isLinux, isPreferringBrowserCodeLoad } from 'vs/base/common/platform';
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { extname } from 'vs/base/common/resources';
type ProtocolCallback = { (result: string | Electron.FilePathWithHeaders | { error: number }): void };
export class FileProtocolHandler extends Disposable {
private readonly validRoots = TernarySearchTree.forUris<boolean>(() => !isLinux);
private readonly validExtensions = new Set(['.png', '.jpg', '.jpeg', '.gif', '.bmp']); // https://github.com/microsoft/vscode/issues/119384
constructor(
@INativeEnvironmentService environmentService: INativeEnvironmentService,
@@ -85,14 +87,23 @@ export class FileProtocolHandler extends Disposable {
const fileUri = URI.parse(request.url);
// isPreferringBrowserCodeLoad: false
// => ensure the file path is in our expected roots
if (!isPreferringBrowserCodeLoad) {
// first check by validRoots
if (this.validRoots.findSubstr(fileUri)) {
return callback({
path: fileUri.fsPath
});
}
// then check by validExtensions
if (this.validExtensions.has(extname(fileUri))) {
return callback({
path: fileUri.fsPath
});
}
// finally block to load the resource
this.logService.error(`${Schemas.file}: Refused to load resource ${fileUri.fsPath} from ${Schemas.file}: protocol (original URL: ${request.url})`);
return callback({ error: -3 /* ABORTED */ });
@@ -114,14 +125,24 @@ export class FileProtocolHandler extends Disposable {
// ensure the root is valid and properly tell Chrome where the
// resource is at.
const fileUri = FileAccess.asFileUri(uri);
// first check by validRoots
if (this.validRoots.findSubstr(fileUri)) {
return callback({
path: fileUri.fsPath
});
} else {
this.logService.error(`${Schemas.vscodeFileResource}: Refused to load resource ${fileUri.fsPath} from ${Schemas.vscodeFileResource}: protocol (original URL: ${request.url})`);
return callback({ error: -3 /* ABORTED */ });
}
// then check by validExtensions
if (this.validExtensions.has(extname(fileUri))) {
return callback({
path: fileUri.fsPath
});
}
// finally block to load the resource
this.logService.error(`${Schemas.vscodeFileResource}: Refused to load resource ${fileUri.fsPath} from ${Schemas.vscodeFileResource}: protocol (original URL: ${request.url})`);
return callback({ error: -3 /* ABORTED */ });
}
}

View File

@@ -37,6 +37,12 @@ interface SearchResult {
state?: string;
}
enum IssueSource {
VSCode = 'vscode',
Extension = 'extension',
Marketplace = 'marketplace'
}
export interface IssueReporterConfiguration extends IWindowConfiguration {
windowId: number;
disableExtensions: boolean;
@@ -53,6 +59,7 @@ export interface IssueReporterConfiguration extends IWindowConfiguration {
commit: string | undefined;
date: string | undefined;
reportIssueUrl: string | undefined;
reportMarketplaceIssueUrl: string | undefined;
}
}
@@ -326,17 +333,18 @@ export class IssueReporter extends Disposable {
hide(problemSourceHelpText);
}
const fileOnExtension = JSON.parse(value);
this.issueReporterModel.update({ fileOnExtension: fileOnExtension });
let fileOnExtension, fileOnMarketplace = false;
if (value === IssueSource.Extension) {
fileOnExtension = true;
} else if (value === IssueSource.Marketplace) {
fileOnMarketplace = true;
}
this.issueReporterModel.update({ fileOnExtension, fileOnMarketplace });
this.render();
const title = (<HTMLInputElement>this.getElementById('issue-title')).value;
if (fileOnExtension) {
this.searchExtensionIssues(title);
} else {
const description = this.issueReporterModel.getData().issueDescription;
this.searchVSCodeIssues(title, description);
}
this.searchIssues(title, fileOnExtension, fileOnMarketplace);
});
this.addEventListener('description', 'input', (e: Event) => {
@@ -353,23 +361,19 @@ export class IssueReporter extends Disposable {
this.addEventListener('issue-title', 'input', (e: Event) => {
const title = (<HTMLInputElement>e.target).value;
const lengthValidationMessage = this.getElementById('issue-title-length-validation-error');
if (title && this.getIssueUrlWithTitle(title).length > MAX_URL_LENGTH) {
const issueUrl = this.getIssueUrl();
if (title && this.getIssueUrlWithTitle(title, issueUrl).length > MAX_URL_LENGTH) {
show(lengthValidationMessage);
} else {
hide(lengthValidationMessage);
}
const fileOnExtension = this.issueReporterModel.fileOnExtension();
if (fileOnExtension === undefined) {
const issueSource = this.getElementById<HTMLSelectElement>('issue-source');
if (!issueSource || issueSource.value === '') {
return;
}
if (fileOnExtension) {
this.searchExtensionIssues(title);
} else {
const description = this.issueReporterModel.getData().issueDescription;
this.searchVSCodeIssues(title, description);
}
const { fileOnExtension, fileOnMarketplace } = this.issueReporterModel.getData();
this.searchIssues(title, fileOnExtension, fileOnMarketplace);
});
this.previewButton.onDidClick(() => this.createIssue());
@@ -489,6 +493,19 @@ export class IssueReporter extends Disposable {
}
}
private searchIssues(title: string, fileOnExtension: boolean | undefined, fileOnMarketplace: boolean | undefined): void {
if (fileOnExtension) {
return this.searchExtensionIssues(title);
}
if (fileOnMarketplace) {
return this.searchMarketplaceIssues(title);
}
const description = this.issueReporterModel.getData().issueDescription;
this.searchVSCodeIssues(title, description);
}
private searchExtensionIssues(title: string): void {
const url = this.getExtensionGitHubUrl();
if (title) {
@@ -509,6 +526,15 @@ export class IssueReporter extends Disposable {
this.clearSearchResults();
}
private searchMarketplaceIssues(title: string): void {
if (title) {
const gitHubInfo = this.parseGitHubUrl(this.configuration.product.reportMarketplaceIssueUrl!);
if (gitHubInfo) {
return this.searchGitHub(`${gitHubInfo.owner}/${gitHubInfo.repositoryName}`, title);
}
}
}
private clearSearchResults(): void {
const similarIssues = this.getElementById('similar-issues')!;
similarIssues.innerText = '';
@@ -636,7 +662,7 @@ export class IssueReporter extends Disposable {
reset(typeSelect,
makeOption(IssueType.Bug, localize('bugReporter', "Bug Report")),
makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request")),
makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue"))
makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue")),
);
typeSelect.value = issueType.toString();
@@ -666,19 +692,15 @@ export class IssueReporter extends Disposable {
}
sourceSelect.innerText = '';
if (issueType === IssueType.FeatureRequest) {
sourceSelect.append(...[
this.makeOption('', localize('selectSource', "Select source"), true),
this.makeOption('false', localize('vscode', "Visual Studio Code"), false),
this.makeOption('true', localize('extension', "An extension"), false)
]);
} else {
sourceSelect.append(...[
this.makeOption('', localize('selectSource', "Select source"), true),
this.makeOption('false', localize('vscode', "Visual Studio Code"), false),
this.makeOption('true', localize('extension', "An extension"), false),
this.makeOption('', localize('unknown', "Don't Know"), false)
]);
sourceSelect.append(this.makeOption('', localize('selectSource', "Select source"), true));
sourceSelect.append(this.makeOption('vscode', localize('vscode', "Visual Studio Code"), false));
sourceSelect.append(this.makeOption('extension', localize('extension', "An extension"), false));
if (this.configuration.product.reportMarketplaceIssueUrl) {
sourceSelect.append(this.makeOption('marketplace', localize('marketplace', "Extensions marketplace"), false));
}
if (issueType !== IssueType.FeatureRequest) {
sourceSelect.append(this.makeOption('', localize('unknown', "Don't know"), false));
}
if (selected !== -1 && selected < sourceSelect.options.length) {
@@ -691,7 +713,7 @@ export class IssueReporter extends Disposable {
private renderBlocks(): void {
// Depending on Issue Type, we render different blocks and text
const { issueType, fileOnExtension } = this.issueReporterModel.getData();
const { issueType, fileOnExtension, fileOnMarketplace } = this.issueReporterModel.getData();
const blockContainer = this.getElementById('block-container');
const systemBlock = document.querySelector('.block-system');
const processBlock = document.querySelector('.block-process');
@@ -715,29 +737,35 @@ export class IssueReporter extends Disposable {
hide(extensionSelector);
if (issueType === IssueType.Bug) {
show(blockContainer);
show(systemBlock);
show(problemSource);
show(experimentsBlock);
if (!fileOnMarketplace) {
show(blockContainer);
show(systemBlock);
show(experimentsBlock);
}
if (fileOnExtension) {
show(extensionSelector);
} else {
} else if (!fileOnMarketplace) {
show(extensionsBlock);
}
reset(descriptionTitle, localize('stepsToReproduce', "Steps to Reproduce"), $('span.required-input', undefined, '*'));
reset(descriptionSubtitle, localize('bugDescription', "Share the steps needed to reliably reproduce the problem. Please include actual and expected results. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub."));
} else if (issueType === IssueType.PerformanceIssue) {
show(blockContainer);
show(systemBlock);
show(processBlock);
show(workspaceBlock);
show(problemSource);
show(experimentsBlock);
if (!fileOnMarketplace) {
show(blockContainer);
show(systemBlock);
show(processBlock);
show(workspaceBlock);
show(experimentsBlock);
}
if (fileOnExtension) {
show(extensionSelector);
} else {
} else if (!fileOnMarketplace) {
show(extensionsBlock);
}
@@ -845,13 +873,13 @@ export class IssueReporter extends Disposable {
const issueTitle = (<HTMLInputElement>this.getElementById('issue-title')).value;
const issueBody = this.issueReporterModel.serialize();
const issueUrl = this.issueReporterModel.fileOnExtension() ? this.getExtensionGitHubUrl() : this.configuration.product.reportIssueUrl!;
const issueUrl = this.getIssueUrl();
const gitHubDetails = this.parseGitHubUrl(issueUrl);
if (this.configuration.data.githubAccessToken && gitHubDetails) {
return this.submitToGitHub(issueTitle, issueBody, gitHubDetails);
}
const baseUrl = this.getIssueUrlWithTitle((<HTMLInputElement>this.getElementById('issue-title')).value);
const baseUrl = this.getIssueUrlWithTitle((<HTMLInputElement>this.getElementById('issue-title')).value, issueUrl);
let url = baseUrl + `&body=${encodeURIComponent(issueBody)}`;
if (url.length > MAX_URL_LENGTH) {
@@ -881,6 +909,14 @@ export class IssueReporter extends Disposable {
});
}
private getIssueUrl(): string {
return this.issueReporterModel.fileOnExtension()
? this.getExtensionGitHubUrl()
: this.issueReporterModel.getData().fileOnMarketplace
? this.configuration.product.reportMarketplaceIssueUrl!
: this.configuration.product.reportIssueUrl!;
}
private parseGitHubUrl(url: string): undefined | { repositoryName: string, owner: string } {
// Assumes a GitHub url to a particular repo, https://github.com/repositoryName/owner.
// Repository name and owner cannot contain '/'
@@ -909,16 +945,12 @@ export class IssueReporter extends Disposable {
return repositoryUrl;
}
private getIssueUrlWithTitle(issueTitle: string): string {
let repositoryUrl = this.configuration.product.reportIssueUrl;
private getIssueUrlWithTitle(issueTitle: string, repositoryUrl: string): string {
if (this.issueReporterModel.fileOnExtension()) {
const extensionGitHubUrl = this.getExtensionGitHubUrl();
if (extensionGitHubUrl) {
repositoryUrl = extensionGitHubUrl + '/issues/new';
}
repositoryUrl = repositoryUrl + '/issues/new';
}
const queryStringPrefix = this.configuration.product.reportIssueUrl && this.configuration.product.reportIssueUrl.indexOf('?') === -1 ? '?' : '&';
const queryStringPrefix = repositoryUrl.indexOf('?') === -1 ? '?' : '&';
return `${repositoryUrl}${queryStringPrefix}title=${encodeURIComponent(issueTitle)}`;
}
@@ -1156,7 +1188,7 @@ export class IssueReporter extends Disposable {
),
...extensions.map(extension => $('tr', undefined,
$('td', undefined, extension.name),
$('td', undefined, extension.publisher.substr(0, 3)),
$('td', undefined, extension.publisher?.substr(0, 3) ?? 'N/A'),
$('td', undefined, extension.version),
))
);

View File

@@ -26,6 +26,7 @@ export interface IssueReporterData {
enabledNonThemeExtesions?: IssueReporterExtensionData[];
extensionsDisabled?: boolean;
fileOnExtension?: boolean;
fileOnMarketplace?: boolean;
selectedExtension?: IssueReporterExtensionData;
actualSearchResults?: ISettingSearchResult[];
query?: string;
@@ -110,30 +111,30 @@ ${this.getInfos()}
let info = '';
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
if (this._data.includeSystemInfo && this._data.systemInfo) {
if (!this._data.fileOnMarketplace && this._data.includeSystemInfo && this._data.systemInfo) {
info += this.generateSystemInfoMd();
}
}
if (this._data.issueType === IssueType.PerformanceIssue) {
if (this._data.includeProcessInfo) {
if (!this._data.fileOnMarketplace && this._data.includeProcessInfo) {
info += this.generateProcessInfoMd();
}
if (this._data.includeWorkspaceInfo) {
if (!this._data.fileOnMarketplace && this._data.includeWorkspaceInfo) {
info += this.generateWorkspaceInfoMd();
}
}
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
if (!this._data.fileOnExtension && this._data.includeExtensions) {
if (!this._data.fileOnMarketplace && !this._data.fileOnExtension && this._data.includeExtensions) {
info += this.generateExtensionsMd();
}
}
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
if (this._data.includeExperiments && this._data.experimentInfo) {
if (!this._data.fileOnMarketplace && this._data.includeExperiments && this._data.experimentInfo) {
info += this.generateExperimentsInfoMd();
}
}
@@ -238,7 +239,7 @@ ${this._data.experimentInfo}
const tableHeader = `Extension|Author (truncated)|Version
---|---|---`;
const table = this._data.enabledNonThemeExtesions.map(e => {
return `${e.name}|${e.publisher.substr(0, 3)}|${e.version}`;
return `${e.name}|${e.publisher?.substr(0, 3) ?? 'N/A'}|${e.version}`;
}).join('\n');
return `<details><summary>Extensions (${this._data.enabledNonThemeExtesions.length})</summary>

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { homedir } from 'os';
import { constants, existsSync, statSync, unlinkSync, chmodSync, truncateSync, readFileSync } from 'fs';
import { existsSync, statSync, unlinkSync, chmodSync, truncateSync, readFileSync } from 'fs';
import { spawn, ChildProcess, SpawnOptions } from 'child_process';
import { buildHelpMessage, buildVersionMessage, OPTIONS } from 'vs/platform/environment/node/argv';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
@@ -23,7 +23,6 @@ function shouldSpawnCliProcess(argv: NativeParsedArgs): boolean {
return !!argv['install-source']
|| !!argv['list-extensions']
|| !!argv['install-extension']
|| !!argv['install-builtin-extension']
|| !!argv['uninstall-extension']
|| !!argv['locate-extension']
|| !!argv['telemetry'];
@@ -84,8 +83,8 @@ export async function main(argv: string[]): Promise<any> {
let restoreMode = false;
if (!!args['file-chmod']) {
targetMode = statSync(target).mode;
if (!(targetMode & constants.S_IWUSR)) {
chmodSync(target, targetMode | constants.S_IWUSR);
if (!(targetMode & 0o200 /* File mode indicating writable by owner */)) {
chmodSync(target, targetMode | 0o200);
restoreMode = true;
}
}

View File

@@ -13,7 +13,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
import { IExtensionManagementService, IExtensionGalleryService, IExtensionManagementCLIService } from 'vs/platform/extensionManagement/common/extensionManagement';
@@ -46,6 +46,7 @@ import { ILocalizationsService } from 'vs/platform/localizations/common/localiza
import { setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { VSBuffer } from 'vs/base/common/buffer';
import { cwd } from 'vs/base/common/process';
class CliMain extends Disposable {
@@ -94,9 +95,12 @@ class CliMain extends Disposable {
private async initServices(): Promise<[IInstantiationService, AppInsightsAppender[]]> {
const services = new ServiceCollection();
// Product
const productService = { _serviceBrand: undefined, ...product };
services.set(IProductService, productService);
// Environment
const environmentService = new NativeEnvironmentService(this.argv);
services.set(IEnvironmentService, environmentService);
const environmentService = new NativeEnvironmentService(this.argv, productService);
services.set(INativeEnvironmentService, environmentService);
// Init folders
@@ -131,9 +135,6 @@ class CliMain extends Disposable {
const stateService = new StateService(environmentService, logService);
services.set(IStateService, stateService);
// Product
services.set(IProductService, { _serviceBrand: undefined, ...product });
const { appRoot, extensionsPath, extensionDevelopmentLocationURI, isBuilt, installSourcePath } = environmentService;
// Request
@@ -149,15 +150,15 @@ class CliMain extends Disposable {
// Telemetry
const appenders: AppInsightsAppender[] = [];
if (isBuilt && !extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) {
if (product.aiConfig && product.aiConfig.asimovKey) {
appenders.push(new AppInsightsAppender('monacoworkbench', null, product.aiConfig.asimovKey));
if (isBuilt && !extensionDevelopmentLocationURI && !environmentService.disableTelemetry && productService.enableTelemetry) {
if (productService.aiConfig && productService.aiConfig.asimovKey) {
appenders.push(new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey));
}
const config: ITelemetryServiceConfig = {
appender: combinedAppender(...appenders),
sendErrorTelemetry: false,
commonProperties: resolveCommonProperties(fileService, release(), process.arch, product.commit, product.version, stateService.getItem('telemetry.machineId'), product.msftInternalDomains, installSourcePath),
commonProperties: resolveCommonProperties(fileService, release(), process.arch, productService.commit, productService.version, stateService.getItem('telemetry.machineId'), productService.msftInternalDomains, installSourcePath),
piiPaths: [appRoot, extensionsPath]
};
@@ -217,7 +218,7 @@ class CliMain extends Disposable {
}
private asExtensionIdOrVSIX(inputs: string[]): (string | URI)[] {
return inputs.map(input => /\.vsix$/i.test(input) ? URI.file(isAbsolute(input) ? input : join(process.cwd(), input)) : input);
return inputs.map(input => /\.vsix$/i.test(input) ? URI.file(isAbsolute(input) ? input : join(cwd(), input)) : input);
}
private async setInstallSource(environmentService: INativeEnvironmentService, fileService: IFileService, installSource: string): Promise<void> {

View File

@@ -7,6 +7,7 @@ import * as nls from 'vs/nls';
import { isFirefox } from 'vs/base/browser/browser';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import * as types from 'vs/base/common/types';
import { status } from 'vs/base/browser/ui/aria/aria';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { Command, EditorCommand, ICommandOptions, registerEditorCommand, MultiCommand, UndoCommand, RedoCommand, SelectAllCommand } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
@@ -280,7 +281,7 @@ abstract class EditorOrNativeTextInputCommand {
constructor(target: MultiCommand) {
// 1. handle case when focus is in editor.
target.addImplementation(10000, (accessor: ServicesAccessor, args: any) => {
target.addImplementation(10000, 'code-editor', (accessor: ServicesAccessor, args: any) => {
// Only if editor text focus (i.e. not if editor has widget focus).
const focusedEditor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
if (focusedEditor && focusedEditor.hasTextFocus()) {
@@ -290,7 +291,7 @@ abstract class EditorOrNativeTextInputCommand {
});
// 2. handle case when focus is in some other `input` / `textarea`.
target.addImplementation(1000, (accessor: ServicesAccessor, args: any) => {
target.addImplementation(1000, 'generic-dom-input-textarea', (accessor: ServicesAccessor, args: any) => {
// Only if focused on an element that allows for entering text
const activeElement = <HTMLElement>document.activeElement;
if (activeElement && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) {
@@ -301,7 +302,7 @@ abstract class EditorOrNativeTextInputCommand {
});
// 3. (default) handle case when focus is somewhere else.
target.addImplementation(0, (accessor: ServicesAccessor, args: any) => {
target.addImplementation(0, 'generic-dom', (accessor: ServicesAccessor, args: any) => {
// Redirecting to active editor
const activeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor();
if (activeEditor) {
@@ -1593,6 +1594,7 @@ export namespace CoreNavigationCommands {
]
);
viewModel.revealPrimaryCursor(args.source, true);
status(nls.localize('removedCursor', "Removed secondary cursors"));
}
});
@@ -1820,7 +1822,7 @@ export namespace CoreEditingCommands {
}
public runCoreEditingCommand(editor: ICodeEditor, viewModel: IViewModel, args: any): void {
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteLeft(viewModel.getPrevEditOperationType(), viewModel.cursorConfig, viewModel.model, viewModel.getCursorStates().map(s => s.modelState.selection));
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteLeft(viewModel.getPrevEditOperationType(), viewModel.cursorConfig, viewModel.model, viewModel.getCursorStates().map(s => s.modelState.selection), viewModel.getCursorAutoClosedCharacters());
if (shouldPushStackElementBefore) {
editor.pushUndoStop();
}

View File

@@ -132,7 +132,7 @@ export class TextAreaHandler extends ViewPart {
this.textArea.setAttribute('aria-haspopup', 'false');
this.textArea.setAttribute('aria-autocomplete', 'both');
if (platform.isWeb && options.get(EditorOption.readOnly)) {
if (options.get(EditorOption.domReadOnly)) {
this.textArea.setAttribute('readonly', 'true');
}
@@ -416,9 +416,8 @@ export class TextAreaHandler extends ViewPart {
this._accessibilitySupport = options.get(EditorOption.accessibilitySupport);
const accessibilityPageSize = options.get(EditorOption.accessibilityPageSize);
if (this._accessibilitySupport === AccessibilitySupport.Enabled && accessibilityPageSize === EditorOptions.accessibilityPageSize.defaultValue) {
// If a screen reader is attached and the default value is not set we shuold automatically increase the page size to 100 for a better experience
// If we put more than 100 lines the nvda can not handle this https://github.com/microsoft/vscode/issues/89717
this._accessibilityPageSize = 100;
// If a screen reader is attached and the default value is not set we shuold automatically increase the page size to 1000 for a better experience
this._accessibilityPageSize = 1000;
} else {
this._accessibilityPageSize = accessibilityPageSize;
}
@@ -441,8 +440,8 @@ export class TextAreaHandler extends ViewPart {
this.textArea.setAttribute('aria-label', this._getAriaLabel(options));
this.textArea.setAttribute('tabindex', String(options.get(EditorOption.tabIndex)));
if (platform.isWeb && e.hasChanged(EditorOption.readOnly)) {
if (options.get(EditorOption.readOnly)) {
if (e.hasChanged(EditorOption.domReadOnly)) {
if (options.get(EditorOption.domReadOnly)) {
this.textArea.setAttribute('readonly', 'true');
} else {
this.textArea.removeAttribute('readonly');

View File

@@ -209,26 +209,30 @@ export class TextAreaInput extends Disposable {
if (
platform.isMacintosh
&& lastKeyDown
&& lastKeyDown.equals(KeyCode.KEY_IN_COMPOSITION)
&& this._textAreaState.selectionStart === this._textAreaState.selectionEnd
&& this._textAreaState.selectionStart > 0
&& this._textAreaState.value.substr(this._textAreaState.selectionStart - 1, 1) === e.data
&& (lastKeyDown.code === 'ArrowRight' || lastKeyDown.code === 'ArrowLeft')
) {
// Handling long press case on macOS + arrow key => pretend the character was selected
if (_debugComposition) {
console.log(`[compositionstart] Handling long press case on macOS + arrow key`, e);
}
this._textAreaState = new TextAreaState(
this._textAreaState.value,
this._textAreaState.selectionStart - 1,
this._textAreaState.selectionEnd,
this._textAreaState.selectionStartPosition ? new Position(this._textAreaState.selectionStartPosition.lineNumber, this._textAreaState.selectionStartPosition.column - 1) : null,
this._textAreaState.selectionEndPosition
const isArrowKey = (
lastKeyDown && lastKeyDown.equals(KeyCode.KEY_IN_COMPOSITION)
&& (lastKeyDown.code === 'ArrowRight' || lastKeyDown.code === 'ArrowLeft')
);
this._onCompositionStart.fire({ revealDeltaColumns: -1 });
return;
if (isArrowKey || browser.isFirefox) {
// Handling long press case on Chromium/Safari macOS + arrow key => pretend the character was selected
// or long press case on Firefox on macOS
if (_debugComposition) {
console.log(`[compositionstart] Handling long press case on macOS + arrow key or Firefox`, e);
}
this._textAreaState = new TextAreaState(
this._textAreaState.value,
this._textAreaState.selectionStart - 1,
this._textAreaState.selectionEnd,
this._textAreaState.selectionStartPosition ? new Position(this._textAreaState.selectionStartPosition.lineNumber, this._textAreaState.selectionStartPosition.column - 1) : null,
this._textAreaState.selectionEndPosition
);
this._onCompositionStart.fire({ revealDeltaColumns: -1 });
return;
}
}
if (browser.isAndroid) {

View File

@@ -23,6 +23,7 @@ import { withNullAsUndefined, assertType } from 'vs/base/common/types';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { ILogService } from 'vs/platform/log/common/log';
export type ServicesAccessor = InstantiationServicesAccessor;
@@ -149,20 +150,26 @@ export abstract class Command {
*/
export type CommandImplementation = (accessor: ServicesAccessor, args: unknown) => boolean | Promise<void>;
interface ICommandImplementationRegistration {
priority: number;
name: string;
implementation: CommandImplementation;
}
export class MultiCommand extends Command {
private readonly _implementations: [number, CommandImplementation][] = [];
private readonly _implementations: ICommandImplementationRegistration[] = [];
/**
* A higher priority gets to be looked at first
*/
public addImplementation(priority: number, implementation: CommandImplementation): IDisposable {
this._implementations.push([priority, implementation]);
this._implementations.sort((a, b) => b[0] - a[0]);
public addImplementation(priority: number, name: string, implementation: CommandImplementation): IDisposable {
this._implementations.push({ priority, name, implementation });
this._implementations.sort((a, b) => b.priority - a.priority);
return {
dispose: () => {
for (let i = 0; i < this._implementations.length; i++) {
if (this._implementations[i][1] === implementation) {
if (this._implementations[i].implementation === implementation) {
this._implementations.splice(i, 1);
return;
}
@@ -172,9 +179,11 @@ export class MultiCommand extends Command {
}
public runCommand(accessor: ServicesAccessor, args: any): void | Promise<void> {
const logService = accessor.get(ILogService);
for (const impl of this._implementations) {
const result = impl[1](accessor, args);
const result = impl.implementation(accessor, args);
if (result) {
logService.trace(`Command '${this.id}' was handled by '${impl.name}'.`);
if (typeof result === 'boolean') {
return;
}
@@ -339,13 +348,13 @@ export abstract class EditorAction extends EditorCommand {
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void>;
}
export abstract class MultiEditorAction extends EditorAction {
export class MultiEditorAction extends EditorAction {
private readonly _implementations: [number, CommandImplementation][] = [];
constructor(opts: IActionOptions) {
super(opts);
}
/**
* A higher priority gets to be looked at first
*/
public addImplementation(priority: number, implementation: CommandImplementation): IDisposable {
this._implementations.push([priority, implementation]);
this._implementations.sort((a, b) => b[0] - a[0]);
@@ -361,20 +370,18 @@ export abstract class MultiEditorAction extends EditorAction {
};
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void> {
this.reportTelemetry(accessor, editor);
public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void> {
for (const impl of this._implementations) {
if (impl[1](accessor, args)) {
return;
const result = impl[1](accessor, args);
if (result) {
if (typeof result === 'boolean') {
return;
}
return result;
}
}
return this.run(accessor, editor, args || {});
}
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void>;
}
//#endregion EditorAction

View File

@@ -88,7 +88,10 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService {
private readonly _editorStyleSheets = new Map<string, RefCountedStyleSheet>();
private readonly _themeService: IThemeService;
constructor(@IThemeService themeService: IThemeService, styleSheet: GlobalStyleSheet | null = null) {
constructor(
styleSheet: GlobalStyleSheet | null,
@IThemeService themeService: IThemeService,
) {
super();
this._globalStyleSheet = styleSheet ? styleSheet : null;
this._themeService = themeService;
@@ -328,7 +331,7 @@ export class DecorationTypeOptionsProvider implements IModelDecorationOptionsPro
}
const _CSS_MAP: { [prop: string]: string; } = {
export const _CSS_MAP: { [prop: string]: string; } = {
color: 'color:{0} !important;',
opacity: 'opacity:{0};',
backgroundColor: 'background-color:{0};',

View File

@@ -166,7 +166,7 @@ export class OpenerService implements IOpenerService {
// check with contributed validators
const targetURI = typeof target === 'string' ? URI.parse(target) : target;
// validate against the original URI that this URI resolves to, if one exists
const validationTarget = this._resolvedUriTargets.get(targetURI) ?? targetURI;
const validationTarget = this._resolvedUriTargets.get(targetURI) ?? target;
for (const validator of this._validators) {
if (!(await validator.shouldOpen(validationTarget))) {
return false;

View File

@@ -106,7 +106,7 @@ export class View extends ViewEventHandler {
// The view context is passed on to most classes (basically to reduce param. counts in ctors)
this._context = new ViewContext(configuration, themeService.getColorTheme(), model);
this._configPixelRatio = this._configPixelRatio = this._context.configuration.options.get(EditorOption.pixelRatio);
this._configPixelRatio = this._context.configuration.options.get(EditorOption.pixelRatio);
// Ensure the view is the first event handler in order to update the layout
this._context.addEventHandler(this);

View File

@@ -121,9 +121,9 @@ export class RangeUtil {
startChildIndex = Math.min(max, Math.max(min, startChildIndex));
endChildIndex = Math.min(max, Math.max(min, endChildIndex));
if (startChildIndex === endChildIndex && startOffset === endOffset && startOffset === 0) {
if (startChildIndex === endChildIndex && startOffset === endOffset && startOffset === 0 && !domNode.children[startChildIndex].firstChild) {
// We must find the position at the beginning of a <span>
// To cover cases of empty <span>s, aboid using a range and use the <span>'s bounding box
// To cover cases of empty <span>s, avoid using a range and use the <span>'s bounding box
const clientRects = domNode.children[startChildIndex].getClientRects();
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft);
}

View File

@@ -509,7 +509,7 @@ const editorConfiguration: IConfigurationNode = {
nls.localize('wordBasedSuggestionsMode.matchingDocuments', 'Suggest words from all open documents of the same language.'),
nls.localize('wordBasedSuggestionsMode.allDocuments', 'Suggest words from all open documents.')
],
description: nls.localize('wordBasedSuggestionsMode', "Controls from what documents word based completions are computed.")
description: nls.localize('wordBasedSuggestionsMode', "Controls from which documents word based completions are computed.")
},
'editor.semanticHighlighting.enabled': {
enum: [true, false, 'configuredByTheme'],

View File

@@ -28,7 +28,7 @@ export type EditorAutoSurroundStrategy = 'languageDefined' | 'quotes' | 'bracket
/**
* Configuration options for typing over closing quotes or brackets
*/
export type EditorAutoClosingOvertypeStrategy = 'always' | 'auto' | 'never';
export type EditorAutoClosingEditStrategy = 'always' | 'auto' | 'never';
/**
* Configuration options for auto indentation in the editor
@@ -139,10 +139,15 @@ export interface IEditorOptions {
*/
extraEditorClassName?: string;
/**
* Should the editor be read only.
* Should the editor be read only. See also `domReadOnly`.
* Defaults to false.
*/
readOnly?: boolean;
/**
* Should the textarea used for input use the DOM `readonly` attribute.
* Defaults to false.
*/
domReadOnly?: boolean;
/**
* Enable linked editing.
* Defaults to false.
@@ -413,10 +418,14 @@ export interface IEditorOptions {
* Defaults to language defined behavior.
*/
autoClosingQuotes?: EditorAutoClosingStrategy;
/**
* Options for pressing backspace near quotes or bracket pairs.
*/
autoClosingDelete?: EditorAutoClosingEditStrategy;
/**
* Options for typing over closing quotes or brackets.
*/
autoClosingOvertype?: EditorAutoClosingOvertypeStrategy;
autoClosingOvertype?: EditorAutoClosingEditStrategy;
/**
* Options for auto surrounding.
* Defaults to always allowing auto surrounding.
@@ -1393,8 +1402,8 @@ class EditorFind extends BaseEditorOption<EditorOption.find, EditorFindOptions>
enum: ['never', 'always', 'multiline'],
default: defaults.autoFindInSelection,
enumDescriptions: [
nls.localize('editor.find.autoFindInSelection.never', 'Never turn on Find in selection automatically (default)'),
nls.localize('editor.find.autoFindInSelection.always', 'Always turn on Find in selection automatically'),
nls.localize('editor.find.autoFindInSelection.never', 'Never turn on Find in selection automatically (default).'),
nls.localize('editor.find.autoFindInSelection.always', 'Always turn on Find in selection automatically.'),
nls.localize('editor.find.autoFindInSelection.multiline', 'Turn on Find in selection automatically when multiple lines of content are selected.')
],
description: nls.localize('find.autoFindInSelection', "Controls the condition for turning on find in selection automatically.")
@@ -3140,7 +3149,7 @@ export interface ISuggestOptions {
*/
snippetsPreventQuickSuggestions?: boolean;
/**
* Favours words that appear close to the cursor.
* Favors words that appear close to the cursor.
*/
localityBonus?: boolean;
/**
@@ -3332,7 +3341,7 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
'editor.suggest.localityBonus': {
type: 'boolean',
default: defaults.localityBonus,
description: nls.localize('suggest.localityBonus', "Controls whether sorting favours words that appear close to the cursor.")
description: nls.localize('suggest.localityBonus', "Controls whether sorting favors words that appear close to the cursor.")
},
'editor.suggest.shareSuggestSelections': {
type: 'boolean',
@@ -3725,6 +3734,7 @@ export const enum EditorOption {
accessibilityPageSize,
ariaLabel,
autoClosingBrackets,
autoClosingDelete,
autoClosingOvertype,
autoClosingQuotes,
autoIndent,
@@ -3746,6 +3756,7 @@ export const enum EditorOption {
cursorWidth,
disableLayerHinting,
disableMonospaceOptimizations,
domReadOnly,
dragAndDrop,
emptySelectionClipboard,
extraEditorClassName,
@@ -3883,7 +3894,10 @@ export const EditorOptions = {
)),
accessibilitySupport: register(new EditorAccessibilitySupport()),
accessibilityPageSize: register(new EditorIntOption(EditorOption.accessibilityPageSize, 'accessibilityPageSize', 10, 1, Constants.MAX_SAFE_SMALL_INTEGER,
{ description: nls.localize('accessibilityPageSize', "Controls the number of lines in the editor that can be read out by a screen reader. Warning: this has a performance implication for numbers larger than the default.") })),
{
description: nls.localize('accessibilityPageSize', "Controls the number of lines in the editor that can be read out by a screen reader at once. When we detect a screen reader we automatically set the default to be 2000. Warning: this has a performance implication for numbers larger than the default."),
deprecationMessage: nls.localize('accessibilityPageSize.deprecated', "This setting is deprecated, editor will automatically choose the accessibility page size when we detect a screen reader. 2000 lines will be the new default.")
})),
ariaLabel: register(new EditorStringOption(
EditorOption.ariaLabel, 'ariaLabel', nls.localize('editorViewAccessibleLabel', "Editor content")
)),
@@ -3901,6 +3915,19 @@ export const EditorOptions = {
description: nls.localize('autoClosingBrackets', "Controls whether the editor should automatically close brackets after the user adds an opening bracket.")
}
)),
autoClosingDelete: register(new EditorStringEnumOption(
EditorOption.autoClosingDelete, 'autoClosingDelete',
'auto' as 'always' | 'auto' | 'never',
['always', 'auto', 'never'] as const,
{
enumDescriptions: [
'',
nls.localize('editor.autoClosingDelete.auto', "Remove adjacent closing quotes or brackets only if they were automatically inserted."),
'',
],
description: nls.localize('autoClosingDelete', "Controls whether the editor should remove adjacent closing quotes or brackets when deleting.")
}
)),
autoClosingOvertype: register(new EditorStringEnumOption(
EditorOption.autoClosingOvertype, 'autoClosingOvertype',
'auto' as 'always' | 'auto' | 'never',
@@ -3963,7 +3990,7 @@ export const EditorOptions = {
)),
stickyTabStops: register(new EditorBooleanOption(
EditorOption.stickyTabStops, 'stickyTabStops', false,
{ description: nls.localize('stickyTabStops', "Emulate selection behaviour of tab characters when using spaces for indentation. Selection will stick to tab stops.") }
{ description: nls.localize('stickyTabStops', "Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.") }
)),
codeLens: register(new EditorBooleanOption(
EditorOption.codeLens, 'codeLens', true,
@@ -4042,6 +4069,9 @@ export const EditorOptions = {
disableMonospaceOptimizations: register(new EditorBooleanOption(
EditorOption.disableMonospaceOptimizations, 'disableMonospaceOptimizations', false
)),
domReadOnly: register(new EditorBooleanOption(
EditorOption.domReadOnly, 'domReadOnly', false,
)),
dragAndDrop: register(new EditorBooleanOption(
EditorOption.dragAndDrop, 'dragAndDrop', true,
{ description: nls.localize('dragAndDrop', "Controls whether the editor should allow moving selections via drag and drop.") }
@@ -4264,7 +4294,7 @@ export const EditorOptions = {
)),
renderLineHighlightOnlyWhenFocus: register(new EditorBooleanOption(
EditorOption.renderLineHighlightOnlyWhenFocus, 'renderLineHighlightOnlyWhenFocus', false,
{ description: nls.localize('renderLineHighlightOnlyWhenFocus', "Controls if the editor should render the current line highlight only when the editor is focused") }
{ description: nls.localize('renderLineHighlightOnlyWhenFocus', "Controls if the editor should render the current line highlight only when the editor is focused.") }
)),
renderValidationDecorations: register(new EditorStringEnumOption(
EditorOption.renderValidationDecorations, 'renderValidationDecorations',
@@ -4280,7 +4310,7 @@ export const EditorOptions = {
'',
nls.localize('renderWhitespace.boundary', "Render whitespace characters except for single spaces between words."),
nls.localize('renderWhitespace.selection', "Render whitespace characters only on selected text."),
nls.localize('renderWhitespace.trailing', "Render only trailing whitespace characters"),
nls.localize('renderWhitespace.trailing', "Render only trailing whitespace characters."),
''
],
description: nls.localize('renderWhitespace', "Controls how the editor should render whitespace characters.")

View File

@@ -620,6 +620,10 @@ export class Cursor extends Disposable {
this._isDoingComposition = isDoingComposition;
}
public getAutoClosedCharacters(): Range[] {
return AutoClosedAction.getAllAutoClosedCharacters(this._autoClosedActions);
}
public startComposition(eventsCollector: ViewModelEventsCollector): void {
this._selectionsWhenCompositionStarted = this.getSelections().slice(0);
}
@@ -628,8 +632,7 @@ export class Cursor extends Disposable {
this._executeEdit(() => {
if (source === 'keyboard') {
// composition finishes, let's check if we need to auto complete if necessary.
const autoClosedCharacters = AutoClosedAction.getAllAutoClosedCharacters(this._autoClosedActions);
this._executeEditOperation(TypeOperations.compositionEndWithInterceptors(this._prevEditOperationType, this.context.cursorConfig, this._model, this._selectionsWhenCompositionStarted, this.getSelections(), autoClosedCharacters));
this._executeEditOperation(TypeOperations.compositionEndWithInterceptors(this._prevEditOperationType, this.context.cursorConfig, this._model, this._selectionsWhenCompositionStarted, this.getSelections(), this.getAutoClosedCharacters()));
this._selectionsWhenCompositionStarted = null;
}
}, eventsCollector, source);
@@ -647,8 +650,7 @@ export class Cursor extends Disposable {
const chr = text.substr(offset, charLength);
// Here we must interpret each typed character individually
const autoClosedCharacters = AutoClosedAction.getAllAutoClosedCharacters(this._autoClosedActions);
this._executeEditOperation(TypeOperations.typeWithInterceptors(this._isDoingComposition, this._prevEditOperationType, this.context.cursorConfig, this._model, this.getSelections(), autoClosedCharacters, chr));
this._executeEditOperation(TypeOperations.typeWithInterceptors(this._isDoingComposition, this._prevEditOperationType, this.context.cursorConfig, this._model, this.getSelections(), this.getAutoClosedCharacters(), chr));
offset += charLength;
}

View File

@@ -87,7 +87,7 @@ export class ColumnSelection {
public static columnSelectLeft(config: CursorConfiguration, model: ICursorSimpleModel, prevColumnSelectData: IColumnSelectData): IColumnSelectResult {
let toViewVisualColumn = prevColumnSelectData.toViewVisualColumn;
if (toViewVisualColumn > 1) {
if (toViewVisualColumn > 0) {
toViewVisualColumn--;
}

View File

@@ -6,7 +6,7 @@
import { CharCode } from 'vs/base/common/charCode';
import { onUnexpectedError } from 'vs/base/common/errors';
import * as strings from 'vs/base/common/strings';
import { EditorAutoClosingStrategy, EditorAutoSurroundStrategy, ConfigurationChangedEvent, EditorAutoClosingOvertypeStrategy, EditorOption, EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
import { EditorAutoClosingStrategy, EditorAutoSurroundStrategy, ConfigurationChangedEvent, EditorAutoClosingEditStrategy, EditorOption, EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { ISelection, Selection } from 'vs/editor/common/core/selection';
@@ -73,7 +73,8 @@ export class CursorConfiguration {
public readonly multiCursorPaste: 'spread' | 'full';
public readonly autoClosingBrackets: EditorAutoClosingStrategy;
public readonly autoClosingQuotes: EditorAutoClosingStrategy;
public readonly autoClosingOvertype: EditorAutoClosingOvertypeStrategy;
public readonly autoClosingDelete: EditorAutoClosingEditStrategy;
public readonly autoClosingOvertype: EditorAutoClosingEditStrategy;
public readonly autoSurround: EditorAutoSurroundStrategy;
public readonly autoIndent: EditorAutoIndentStrategy;
public readonly autoClosingPairs: AutoClosingPairs;
@@ -92,6 +93,7 @@ export class CursorConfiguration {
|| e.hasChanged(EditorOption.multiCursorPaste)
|| e.hasChanged(EditorOption.autoClosingBrackets)
|| e.hasChanged(EditorOption.autoClosingQuotes)
|| e.hasChanged(EditorOption.autoClosingDelete)
|| e.hasChanged(EditorOption.autoClosingOvertype)
|| e.hasChanged(EditorOption.autoSurround)
|| e.hasChanged(EditorOption.useTabStops)
@@ -125,6 +127,7 @@ export class CursorConfiguration {
this.multiCursorPaste = options.get(EditorOption.multiCursorPaste);
this.autoClosingBrackets = options.get(EditorOption.autoClosingBrackets);
this.autoClosingQuotes = options.get(EditorOption.autoClosingQuotes);
this.autoClosingDelete = options.get(EditorOption.autoClosingDelete);
this.autoClosingOvertype = options.get(EditorOption.autoClosingOvertype);
this.autoSurround = options.get(EditorOption.autoSurround);
this.autoIndent = options.get(EditorOption.autoIndent);

View File

@@ -5,7 +5,7 @@
import * as strings from 'vs/base/common/strings';
import { ReplaceCommand } from 'vs/editor/common/commands/replaceCommand';
import { EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
import { EditorAutoClosingEditStrategy, EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
import { CursorColumns, CursorConfiguration, EditOperationResult, EditOperationType, ICursorSimpleModel, isQuote } from 'vs/editor/common/controller/cursorCommon';
import { MoveOperations } from 'vs/editor/common/controller/cursorMoveOperations';
import { Range } from 'vs/editor/common/core/range';
@@ -50,15 +50,20 @@ export class DeleteOperations {
}
public static isAutoClosingPairDelete(
autoClosingDelete: EditorAutoClosingEditStrategy,
autoClosingBrackets: EditorAutoClosingStrategy,
autoClosingQuotes: EditorAutoClosingStrategy,
autoClosingPairsOpen: Map<string, StandardAutoClosingPairConditional[]>,
model: ICursorSimpleModel,
selections: Selection[]
selections: Selection[],
autoClosedCharacters: Range[]
): boolean {
if (autoClosingBrackets === 'never' && autoClosingQuotes === 'never') {
return false;
}
if (autoClosingDelete === 'never') {
return false;
}
for (let i = 0, len = selections.length; i < len; i++) {
const selection = selections[i];
@@ -100,6 +105,21 @@ export class DeleteOperations {
if (!foundAutoClosingPair) {
return false;
}
// Must delete the pair only if it was automatically inserted by the editor
if (autoClosingDelete === 'auto') {
let found = false;
for (let j = 0, lenJ = autoClosedCharacters.length; j < lenJ; j++) {
const autoClosedCharacter = autoClosedCharacters[j];
if (position.lineNumber === autoClosedCharacter.startLineNumber && position.column === autoClosedCharacter.startColumn) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
}
return true;
@@ -120,9 +140,9 @@ export class DeleteOperations {
return [true, commands];
}
public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, Array<ICommand | null>] {
public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[], autoClosedCharacters: Range[]): [boolean, Array<ICommand | null>] {
if (this.isAutoClosingPairDelete(config.autoClosingBrackets, config.autoClosingQuotes, config.autoClosingPairs.autoClosingPairsOpenByEnd, model, selections)) {
if (this.isAutoClosingPairDelete(config.autoClosingDelete, config.autoClosingBrackets, config.autoClosingQuotes, config.autoClosingPairs.autoClosingPairsOpenByEnd, model, selections, autoClosedCharacters)) {
return this._runAutoClosingPairDelete(config, model, selections);
}

View File

@@ -5,7 +5,7 @@
import { CharCode } from 'vs/base/common/charCode';
import * as strings from 'vs/base/common/strings';
import { EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
import { EditorAutoClosingEditStrategy, EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
import { CursorConfiguration, ICursorSimpleModel, SingleCursorState } from 'vs/editor/common/controller/cursorCommon';
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
import { WordCharacterClass, WordCharacterClassifier, getMapForWordSeparators } from 'vs/editor/common/controller/wordCharacterClassifier';
@@ -52,9 +52,11 @@ export interface DeleteWordContext {
model: ITextModel;
selection: Selection;
whitespaceHeuristics: boolean;
autoClosingDelete: EditorAutoClosingEditStrategy;
autoClosingBrackets: EditorAutoClosingStrategy;
autoClosingQuotes: EditorAutoClosingStrategy;
autoClosingPairs: AutoClosingPairs;
autoClosedCharacters: Range[];
}
export class WordOperations {
@@ -384,7 +386,7 @@ export class WordOperations {
return selection;
}
if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpenByEnd, ctx.model, [ctx.selection])) {
if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingDelete, ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpenByEnd, ctx.model, [ctx.selection], ctx.autoClosedCharacters)) {
const position = ctx.selection.getPosition();
return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1);
}

View File

@@ -23,10 +23,26 @@ export interface IStringBuilder {
appendASCIIString(str: string): void;
}
let _utf16LE_TextDecoder: TextDecoder | null;
function getUTF16LE_TextDecoder(): TextDecoder {
if (!_utf16LE_TextDecoder) {
_utf16LE_TextDecoder = new TextDecoder('UTF-16LE');
}
return _utf16LE_TextDecoder;
}
let _utf16BE_TextDecoder: TextDecoder | null;
function getUTF16BE_TextDecoder(): TextDecoder {
if (!_utf16BE_TextDecoder) {
_utf16BE_TextDecoder = new TextDecoder('UTF-16BE');
}
return _utf16BE_TextDecoder;
}
let _platformTextDecoder: TextDecoder | null;
export function getPlatformTextDecoder(): TextDecoder {
if (!_platformTextDecoder) {
_platformTextDecoder = new TextDecoder(platform.isLittleEndian() ? 'UTF-16LE' : 'UTF-16BE');
_platformTextDecoder = platform.isLittleEndian() ? getUTF16LE_TextDecoder() : getUTF16BE_TextDecoder();
}
return _platformTextDecoder;
}
@@ -45,7 +61,14 @@ if (hasTextDecoder) {
function standardDecodeUTF16LE(source: Uint8Array, offset: number, len: number): string {
const view = new Uint16Array(source.buffer, offset, len);
return getPlatformTextDecoder().decode(view);
if (len > 0 && (view[0] === 0xFEFF || view[0] === 0xFFFE)) {
// UTF16 sometimes starts with a BOM https://de.wikipedia.org/wiki/Byte_Order_Mark
// It looks like TextDecoder.decode will eat up a leading BOM (0xFEFF or 0xFFFE)
// We don't want that behavior because we know the string is UTF16LE and the BOM should be maintained
// So we use the manual decoder
return compatDecodeUTF16LE(source, offset, len);
}
return getUTF16LE_TextDecoder().decode(view);
}
function compatDecodeUTF16LE(source: Uint8Array, offset: number, len: number): string {

View File

@@ -19,7 +19,7 @@ function uriGetComparisonKey(resource: URI): string {
return resource.toString();
}
class SingleModelEditStackData {
export class SingleModelEditStackData {
public static create(model: ITextModel, beforeCursorState: Selection[] | null): SingleModelEditStackData {
const alternativeVersionId = model.getAlternativeVersionId();

View File

@@ -881,55 +881,49 @@ export class TextModel extends Disposable implements model.ITextModel {
* Validates `range` is within buffer bounds, but allows it to sit in between surrogate pairs, etc.
* Will try to not allocate if possible.
*/
private _validateRangeRelaxedNoAllocations(range: IRange): Range {
public _validateRangeRelaxedNoAllocations(range: IRange): Range {
const linesCount = this._buffer.getLineCount();
const initialStartLineNumber = range.startLineNumber;
const initialStartColumn = range.startColumn;
let startLineNumber: number;
let startColumn: number;
let startLineNumber = Math.floor((typeof initialStartLineNumber === 'number' && !isNaN(initialStartLineNumber)) ? initialStartLineNumber : 1);
let startColumn = Math.floor((typeof initialStartColumn === 'number' && !isNaN(initialStartColumn)) ? initialStartColumn : 1);
if (initialStartLineNumber < 1) {
if (startLineNumber < 1) {
startLineNumber = 1;
startColumn = 1;
} else if (initialStartLineNumber > linesCount) {
} else if (startLineNumber > linesCount) {
startLineNumber = linesCount;
startColumn = this.getLineMaxColumn(startLineNumber);
} else {
startLineNumber = initialStartLineNumber | 0;
if (initialStartColumn <= 1) {
if (startColumn <= 1) {
startColumn = 1;
} else {
const maxColumn = this.getLineMaxColumn(startLineNumber);
if (initialStartColumn >= maxColumn) {
if (startColumn >= maxColumn) {
startColumn = maxColumn;
} else {
startColumn = initialStartColumn | 0;
}
}
}
const initialEndLineNumber = range.endLineNumber;
const initialEndColumn = range.endColumn;
let endLineNumber: number;
let endColumn: number;
let endLineNumber = Math.floor((typeof initialEndLineNumber === 'number' && !isNaN(initialEndLineNumber)) ? initialEndLineNumber : 1);
let endColumn = Math.floor((typeof initialEndColumn === 'number' && !isNaN(initialEndColumn)) ? initialEndColumn : 1);
if (initialEndLineNumber < 1) {
if (endLineNumber < 1) {
endLineNumber = 1;
endColumn = 1;
} else if (initialEndLineNumber > linesCount) {
} else if (endLineNumber > linesCount) {
endLineNumber = linesCount;
endColumn = this.getLineMaxColumn(endLineNumber);
} else {
endLineNumber = initialEndLineNumber | 0;
if (initialEndColumn <= 1) {
if (endColumn <= 1) {
endColumn = 1;
} else {
const maxColumn = this.getLineMaxColumn(endLineNumber);
if (initialEndColumn >= maxColumn) {
if (endColumn >= maxColumn) {
endColumn = maxColumn;
} else {
endColumn = initialEndColumn | 0;
}
}
}

View File

@@ -297,11 +297,11 @@ export interface EvaluatableExpressionProvider {
}
/**
* An open ended information bag passed to the inline value provider.
* A minimal context containes just the document location where the debugger has stopped.
* A value-object that contains contextual information when requesting inline values from a InlineValuesProvider.
* @internal
*/
export interface InlineValueContext {
frameId: number;
stoppedLocation: Range;
}
@@ -699,8 +699,8 @@ export interface CodeAction {
* @internal
*/
export const enum CodeActionTriggerType {
Auto = 1,
Manual = 2,
Invoke = 1,
Auto = 2,
}
/**
@@ -1683,33 +1683,6 @@ export interface CommentThreadChangedEvent {
readonly changed: CommentThread[];
}
/**
* @internal
*/
export interface IWebviewPortMapping {
webviewPort: number;
extensionHostPort: number;
}
/**
* @internal
*/
export interface IWebviewOptions {
readonly enableScripts?: boolean;
readonly enableCommandUris?: boolean;
readonly localResourceRoots?: ReadonlyArray<UriComponents>;
readonly portMapping?: ReadonlyArray<IWebviewPortMapping>;
}
/**
* @internal
*/
export interface IWebviewPanelOptions {
readonly enableFindWidget?: boolean;
readonly retainContextWhenHidden?: boolean;
}
export interface CodeLens {
range: IRange;
id?: string;

View File

@@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { mergeSort } from 'vs/base/common/arrays';
import { stringDiff } from 'vs/base/common/diff/diff';
import { IDisposable } from 'vs/base/common/lifecycle';
import { globals } from 'vs/base/common/platform';
@@ -455,7 +454,7 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable {
const result: TextEdit[] = [];
let lastEol: EndOfLineSequence | undefined = undefined;
edits = mergeSort(edits, (a, b) => {
edits = edits.slice(0).sort((a, b) => {
if (a.range && b.range) {
return Range.compareRangesUsingStarts(a.range, b.range);
}

View File

@@ -741,6 +741,19 @@ export class ModelSemanticColoring extends Disposable {
this._fetchDocumentSemanticTokens.schedule();
}
}));
this._register(this._model.onDidChangeLanguage(() => {
// clear any outstanding state
if (this._currentDocumentResponse) {
this._currentDocumentResponse.dispose();
this._currentDocumentResponse = null;
}
if (this._currentDocumentRequestCancellationTokenSource) {
this._currentDocumentRequestCancellationTokenSource.cancel();
this._currentDocumentRequestCancellationTokenSource = null;
}
this._setDocumentSemanticTokens(null, null, null, []);
this._fetchDocumentSemanticTokens.schedule(0);
}));
const bindDocumentChangeListeners = () => {
dispose(this._documentProvidersChangeListeners);
this._documentProvidersChangeListeners = [];

Some files were not shown because too many files have changed in this diff Show More