Skip to content

Commit 040bfba

Browse files
1 parent 07b4da7 commit 040bfba

2 files changed

Lines changed: 12 additions & 92 deletions

File tree

Source/IPC/WindServiceHandlers/Extensions.rs

Lines changed: 6 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -7,97 +7,11 @@ use std::sync::Arc;
77
use CommonLibrary::ExtensionManagement::ExtensionManagementService::ExtensionManagementService;
88
use serde_json::{Value, json};
99

10-
use crate::{dev_log, RunTime::ApplicationRunTime::ApplicationRunTime};
11-
12-
/// `MarshalledId.Uri` from VS Code's `src/vs/base/common/marshallingIds.ts`.
13-
/// VS Code's `transformAndReviveIncomingURIs` walks every property of every
14-
/// object returned from the IPC channel and only calls `URI.revive()` on
15-
/// nested objects that carry `$mid === 1`. Without this marker the extension
16-
/// location surfaces as a plain `UriComponents` bag; downstream
17-
/// `resources.joinPath(local.location, …)` then trips on
18-
/// `uri.with is not a function` the moment the sidebar tries to build an
19-
/// icon URL. Every UriComponents we produce has to carry `$mid: 1`.
20-
const MID_URI:u64 = 1;
21-
22-
/// Reshape an `extensionLocation` field into VS Code's `UriComponents` object
23-
/// form. The extension scanner stores it as a raw `file://` URL string; the
24-
/// renderer's URI reviver is keyed off the `$mid` marshalling marker and only
25-
/// revives objects that carry it, so the emitted shape must always include
26-
/// `$mid: 1` alongside the usual `scheme / authority / path / query /
27-
/// fragment` fields - otherwise the sidebar silently filters the whole batch
28-
/// out (no `$mid` ⇒ no revive ⇒ `.fsPath` / `.with` undefined).
29-
fn Normalize_Location_To_UriComponents(Raw:Option<&Value>) -> Value {
30-
let Base = match Raw {
31-
Some(Value::Object(Map)) if Map.contains_key("scheme") => Value::Object(Map.clone()),
32-
Some(Value::String(Url)) => Parse_File_Url_To_UriComponents(Url),
33-
_ => json!({
34-
"scheme": "file",
35-
"authority": "",
36-
"path": "/extensions/unknown",
37-
"query": "",
38-
"fragment": "",
39-
}),
40-
};
41-
Stamp_Mid_Uri(Base)
42-
}
43-
44-
/// Attach `$mid: 1` to a `UriComponents` object if it isn't already present.
45-
/// Guards against both missing markers (the common case; Mountain built the
46-
/// object ourselves) and pre-marked payloads (passthrough from an upstream
47-
/// service that already tagged it). Returns the input unchanged for any
48-
/// non-object value - callers are expected to have already produced a shape.
49-
fn Stamp_Mid_Uri(Input:Value) -> Value {
50-
match Input {
51-
Value::Object(mut Map) => {
52-
Map.entry("$mid".to_string()).or_insert(json!(MID_URI));
53-
Value::Object(Map)
54-
}
55-
Other => Other,
56-
}
57-
}
58-
59-
/// Minimal `file://` URL → `UriComponents` parser. Accepts
60-
/// `file:///absolute/path` (authority empty) and preserves the path verbatim.
61-
/// Non-`file:` schemes are parsed generically (scheme: path).
62-
fn Parse_File_Url_To_UriComponents(Url:&str) -> Value {
63-
if let Some(Rest) = Url.strip_prefix("file://") {
64-
// `file:///Volumes/...` → authority="", path="/Volumes/..."
65-
let (Authority, Path) = match Rest.find('/') {
66-
Some(0) => ("", Rest),
67-
Some(Index) => (&Rest[..Index], &Rest[Index..]),
68-
None => ("", ""),
69-
};
70-
return json!({
71-
"scheme": "file",
72-
"authority": Authority,
73-
"path": Path,
74-
"query": "",
75-
"fragment": "",
76-
});
77-
}
78-
if let Some((Scheme, PathPart)) = Url.split_once(':') {
79-
let Trimmed = PathPart.trim_start_matches("//");
80-
let (Authority, Path) = match Trimmed.find('/') {
81-
Some(0) => ("", Trimmed),
82-
Some(Index) => (&Trimmed[..Index], &Trimmed[Index..]),
83-
None => ("", Trimmed),
84-
};
85-
return json!({
86-
"scheme": Scheme,
87-
"authority": Authority,
88-
"path": Path,
89-
"query": "",
90-
"fragment": "",
91-
});
92-
}
93-
json!({
94-
"scheme": "file",
95-
"authority": "",
96-
"path": Url,
97-
"query": "",
98-
"fragment": "",
99-
})
100-
}
10+
use crate::{
11+
IPC::UriComponents::{Normalize as NormalizeUri, StampMidUri},
12+
RunTime::ApplicationRunTime::ApplicationRunTime,
13+
dev_log,
14+
};
10115

10216
/// Return scanned extensions reshaped as VS Code's `ILocalExtension[]`
10317
/// so `ExtensionManagementChannelClient.getInstalled` can destructure
@@ -128,7 +42,7 @@ pub async fn handle_extensions_get_installed(runtime:Arc<ApplicationRunTime>) ->
12842
// filtered out. Normalize once, reuse for both the top-level
12943
// `location` and the mirror inside `manifest.extensionLocation` so
13044
// callers that read either field get the same shape.
131-
let Location = Normalize_Location_To_UriComponents(Manifest.get("extensionLocation"));
45+
let Location = NormalizeUri(Manifest.get("extensionLocation"));
13246
let mut Manifest = Manifest;
13347
if let Value::Object(ref mut Map) = Manifest {
13448
Map.insert("extensionLocation".to_string(), Location.clone());

Source/IPC/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ pub mod WindServiceAdapters;
119119
/// available.
120120
pub mod DevLog;
121121

122+
/// Shared `UriComponents` emitter. Every handler that returns a URI to the
123+
/// renderer must route through this module so the `$mid: 1` marshalling
124+
/// marker is never forgotten (without it VS Code's IPC reviver skips the
125+
/// field and `uri.with is not a function` cascades through the sidebar).
126+
pub mod UriComponents;
127+
122128
/// Legacy Wind Service Handlers.
123129
pub mod WindServiceHandlers;
124130

0 commit comments

Comments
 (0)