Change:
Following test throws: I found this while investigating At that point the editor component is quite broken because of a lot of errors being thrown. Notice how not even a tab shows for the editor: <img width="1058" alt="image" src="https://user-"
that should already throw because at least a scheme is needed. It doesn't because was designed to be the runtime counter part of which never produces such output so some IPC deserialisation cost can be saved.
, that works for me and will also throw when we get bad objects into such as the from
Yeah, my plan is to add an argument like we have in other URI-places. It will default to true and only IPC should be relaxed
Not doing that because it actually already exists as . I believe the adoption/migration task is to use instead of whenever getting uri components from storage or esp from command arguments. Tho, there is one special case for which is that it automatically uses when the scheme is missing. We could make that configurable but a check for might make this obsolete
Closing this after and the ask to use when creating uri from "untrusted" sources
I will see to adopt , I forgot we had it

Discussion:
return new Uri('file', authority, path, _empty, _empty); } <del> static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI { </del> <ins> /** * Creates new URI from uri components. * * Unless `strict` is `true` the scheme is defaults to be `file`. This function performs * validation and should be used for untrusted uri components retrieved from storage, * user input, command arguments etc */ static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }, strict?: boolean): URI { </ins> const result = new Uri( components.scheme, components.authority, components.path, components.query, components.fragment, <ins> strict </ins> ); <del> _validateUri(result, true); </del> return result; }

return this; } <ins> /** * A helper function to revive URIs. * * **Note** that this function should only be used when receiving URI#toJSON generated data * and that it doesn't do any validation. Use {@link URI.from} when received "untrusted" * uri components such as command arguments or data from storage. * * @param data The URI components or URI to revive. * @returns The revived URI or undefined or null. */ </ins> static revive(data: UriComponents | URI): URI; static revive(data: UriComponents | URI | undefined): URI | undefined; static revive(data: UriComponents | URI | null): URI | null;

return data; } else { const result = new Uri(data); <del> result._formatted = (<UriState>data).external; result._fsPath = (<UriState>data)._sep === _pathSepMarker ? (<UriState>data).fsPath : null; </del> <ins> result._formatted = (<UriState>data).external ?? null; result._fsPath = (<UriState>data)._sep === _pathSepMarker ? (<UriState>data).fsPath ?? null : null; </ins> return result; } }

export interface UriComponents { scheme: string; <del> authority: string; path: string; query: string; fragment: string; </del> <ins> authority?: string; path?: string; query?: string; fragment?: string; } export function isUriComponents(thing: any): thing is UriComponents { if (!thing || typeof thing !== 'object') { return false; } return typeof (<UriComponents>thing).scheme === 'string' && (typeof (<UriComponents>thing).authority === 'string' || typeof (<UriComponents>thing).authority === 'undefined') && (typeof (<UriComponents>thing).path === 'string' || typeof (<UriComponents>thing).path === 'undefined') && (typeof (<UriComponents>thing).query === 'string' || typeof (<UriComponents>thing).query === 'undefined') && (typeof (<UriComponents>thing).fragment === 'string' || typeof (<UriComponents>thing).fragment === 'undefined'); </ins> } interface UriState extends UriComponents { $mid: MarshalledId.Uri; <del> external: string; fsPath: string; _sep: 1 | undefined; </del> <ins> external?: string; fsPath?: string; _sep?: 1; </ins> } const _pathSepMarker = isWindows ? 1 : undefined;

if (this._formatted) { res.external = this._formatted; } <del> // uri components </del> <ins> //--- uri components </ins> if (this.path) { res.path = this.path; } <ins> // TODO // this isn't correct and can violate the UriComponents contract but // this is part of the vscode.Uri API and we shouldn't change how that // works anymore </ins> if (this.scheme) { res.scheme = this.scheme; }

*--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; import { isWindows } from 'vs/base/common/platform'; <del> import { URI, UriComponents } from 'vs/base/common/uri'; </del> <ins> import { URI, UriComponents, isUriComponents } from 'vs/base/common/uri'; </ins> suite('URI', () => {

}), true); }); <ins> test('isUriComponents', function () { assert.ok(isUriComponents(URI.file('a'))); assert.ok(isUriComponents(URI.file('a').toJSON())); assert.ok(isUriComponents(URI.file(''))); assert.ok(isUriComponents(URI.file('').toJSON())); assert.strictEqual(isUriComponents(1), false); assert.strictEqual(isUriComponents(true), false); assert.strictEqual(isUriComponents("true"), false); assert.strictEqual(isUriComponents({}), false); assert.strictEqual(isUriComponents({ scheme: '' }), true); // valid components but INVALID uri assert.strictEqual(isUriComponents({ scheme: 'fo' }), true); assert.strictEqual(isUriComponents({ scheme: 'fo', path: '/p' }), true); assert.strictEqual(isUriComponents({ path: '/p' }), false); }); test('from, from(strict), revive', function () { assert.throws(() => URI.from({ scheme: '' }, true)); assert.strictEqual(URI.from({ scheme: '' }).scheme, 'file'); assert.strictEqual(URI.revive({ scheme: '' }).scheme, ''); }); </ins> test('Unable to open '%A0.txt': URI malformed #76506, part 2', function () { assert.strictEqual(URI.parse('file://some/%.txt').toString(), 'file://some/%25.txt'); assert.strictEqual(URI.parse('file://some/%A0.txt').toString(), 'file://some/%25A0.txt');

* @param path A file system path (see `Uri#fsPath`) */ static file(path: string): Uri; <ins> /** * Creates new Uri from uri components. * * Unless `strict` is `true` the scheme is defaults to be `file`. This function performs * validation and should be used for untrusted uri components retrieved from storage, * user input, command arguments etc */ </ins> static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string; <del> }): Uri; </del> <ins> }, strict?: boolean): Uri; </ins> /** * Join a Uri path with path fragments and normalizes the resulting path. *

*/ toString(skipEncoding?: boolean): string; toJSON(): UriComponents; <ins> /** * A helper function to revive URIs. * * **Note** that this function should only be used when receiving Uri#toJSON generated data * and that it doesn't do any validation. Use {@link Uri.from} when received "untrusted" * uri components such as command arguments or data from storage. * * @param data The Uri components or Uri to revive. * @returns The revived Uri or undefined or null. */ </ins> static revive(data: UriComponents | Uri): Uri; static revive(data: UriComponents | Uri | undefined): Uri | undefined; static revive(data: UriComponents | Uri | null): Uri | null;

export interface UriComponents { scheme: string; <del> authority: string; path: string; query: string; fragment: string; </del> <ins> authority?: string; path?: string; query?: string; fragment?: string; </ins> } /** * Virtual Key Codes, the value does not hold any inherent meaning.