@lvce-editor/extension-management-worker 4.73.0 → 4.74.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensionManagementWorkerMain.js +291 -187
- package/package.json +1 -1
|
@@ -1986,177 +1986,14 @@ const createExtensionCommandExecutor = commandMap => {
|
|
|
1986
1986
|
};
|
|
1987
1987
|
};
|
|
1988
1988
|
|
|
1989
|
-
const
|
|
1990
|
-
const
|
|
1991
|
-
const
|
|
1992
|
-
|
|
1993
|
-
return applicationRpcs.get(applicationId)?.get(extensionId);
|
|
1994
|
-
}
|
|
1995
|
-
return rpcs$1[extensionId];
|
|
1996
|
-
};
|
|
1997
|
-
const getAll = applicationId => {
|
|
1998
|
-
if (applicationId !== undefined) {
|
|
1999
|
-
return [...(applicationRpcs.get(applicationId)?.values() || [])];
|
|
2000
|
-
}
|
|
2001
|
-
return Object.values(rpcs$1);
|
|
2002
|
-
};
|
|
2003
|
-
const getIds = applicationId => {
|
|
2004
|
-
if (applicationId !== undefined) {
|
|
2005
|
-
return [...(applicationRpcs.get(applicationId)?.keys() || [])];
|
|
2006
|
-
}
|
|
2007
|
-
return Object.keys(rpcs$1);
|
|
2008
|
-
};
|
|
2009
|
-
const set$2 = (extensionId, rpc, applicationId) => {
|
|
2010
|
-
if (applicationId !== undefined) {
|
|
2011
|
-
const entries = applicationRpcs.get(applicationId) || new Map();
|
|
2012
|
-
entries.set(extensionId, rpc);
|
|
2013
|
-
applicationRpcs.set(applicationId, entries);
|
|
2014
|
-
return;
|
|
2015
|
-
}
|
|
2016
|
-
rpcs$1[extensionId] = rpc;
|
|
2017
|
-
};
|
|
2018
|
-
const remove$1 = (extensionId, applicationId) => {
|
|
2019
|
-
const rpc = rpcs$1[extensionId];
|
|
2020
|
-
delete rpcs$1[extensionId];
|
|
2021
|
-
return rpc;
|
|
2022
|
-
};
|
|
2023
|
-
const clear = applicationId => {
|
|
2024
|
-
if (applicationId !== undefined) {
|
|
2025
|
-
applicationRpcs.delete(applicationId);
|
|
2026
|
-
return;
|
|
2027
|
-
}
|
|
2028
|
-
for (const key of Object.keys(rpcs$1)) {
|
|
2029
|
-
delete rpcs$1[key];
|
|
2030
|
-
}
|
|
2031
|
-
};
|
|
2032
|
-
|
|
2033
|
-
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
2034
|
-
|
|
2035
|
-
const pendingRpcs = Object.create(null);
|
|
2036
|
-
const getPendingExtensionIds = application => {
|
|
2037
|
-
return Object.keys(pendingRpcs).flatMap(key => {
|
|
2038
|
-
const [applicationId, generation, extensionId] = JSON.parse(key);
|
|
2039
|
-
return applicationId === application.applicationId && generation === application.applicationGeneration ? [extensionId] : [];
|
|
2040
|
-
});
|
|
2041
|
-
};
|
|
2042
|
-
const getRuntimeId = (extensionId, application) => {
|
|
2043
|
-
return application?.applicationId === undefined ? extensionId : JSON.stringify([application.applicationId, application.applicationGeneration, extensionId]);
|
|
2044
|
-
};
|
|
2045
|
-
const bindCommandMap = (rpc, commandMap) => {
|
|
2046
|
-
if (rpc.ipc) {
|
|
2047
|
-
rpc.ipc.execute = createExtensionCommandExecutor(commandMap);
|
|
2048
|
-
}
|
|
2049
|
-
return rpc;
|
|
2050
|
-
};
|
|
2051
|
-
const createIsolatedExtensionHostWorker = async (extensionId, absolutePath, workerName, contentSecurityPolicy, createRpc, invokeAndTransfer, application) => {
|
|
2052
|
-
const runtimeId = getRuntimeId(extensionId, application);
|
|
2053
|
-
const invokeCommand = application === undefined ? undefined : (method, ...args) => {
|
|
2054
|
-
assertCurrentApplication(application);
|
|
2055
|
-
if (method === 'Extensions.registerFileChangeHandler') {
|
|
2056
|
-
return register$1(extensionId, application.applicationId);
|
|
2057
|
-
}
|
|
2058
|
-
if (method === 'Extensions.unregisterFileChangeHandler') {
|
|
2059
|
-
return unregister(extensionId, application.applicationId);
|
|
2060
|
-
}
|
|
2061
|
-
const invokeApplication = commandMapRef['Extensions.invokeForApplication'];
|
|
2062
|
-
if (!invokeApplication) {
|
|
2063
|
-
throw new Error('Application extension command routing is not initialized');
|
|
2064
|
-
}
|
|
2065
|
-
return invokeApplication(application.applicationId, method, ...args);
|
|
2066
|
-
};
|
|
2067
|
-
const commandMap = createExtensionCommandMap(runtimeId, invokeCommand);
|
|
2068
|
-
const rpc = await createRpc({
|
|
2069
|
-
// PlainMessagePortRpc registers this map process-wide. Bind the restricted
|
|
2070
|
-
// callbacks to this port below, never to the shared host command table.
|
|
2071
|
-
commandMap: {},
|
|
2072
|
-
isMessagePortOpen: true,
|
|
2073
|
-
send(port) {
|
|
2074
|
-
return invokeAndTransfer('LaunchIsolatedExtensionHostWorker.launchIsolatedExtensionHostWorker', port, runtimeId, absolutePath, workerName, contentSecurityPolicy);
|
|
2075
|
-
}
|
|
2076
|
-
});
|
|
2077
|
-
return bindCommandMap(rpc, commandMap);
|
|
2078
|
-
};
|
|
2079
|
-
const createWorker$1 = (extensionId, absolutePath, workerName, contentSecurityPolicy, application) => {
|
|
2080
|
-
return createIsolatedExtensionHostWorker(extensionId, absolutePath, workerName, contentSecurityPolicy, create$6, invokeAndTransfer, application);
|
|
2081
|
-
};
|
|
2082
|
-
const createAndStoreRpc = async (extensionId, absolutePath, workerName, contentSecurityPolicy, create, application) => {
|
|
2083
|
-
try {
|
|
2084
|
-
const rpc = application === undefined ? await create(extensionId, absolutePath, workerName, contentSecurityPolicy) : await create(extensionId, absolutePath, workerName, contentSecurityPolicy, application);
|
|
2085
|
-
if (application !== undefined) {
|
|
2086
|
-
try {
|
|
2087
|
-
assertCurrentApplication(application);
|
|
2088
|
-
} catch (error) {
|
|
2089
|
-
await Promise.allSettled([rpc.dispose(), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
|
|
2090
|
-
throw error;
|
|
2091
|
-
}
|
|
2092
|
-
}
|
|
2093
|
-
set$2(extensionId, rpc, application?.applicationId);
|
|
2094
|
-
return rpc;
|
|
2095
|
-
} catch (error) {
|
|
2096
|
-
console.error(`[extension-management-worker] ${extensionId} failed to activate`, error);
|
|
2097
|
-
throw error;
|
|
2098
|
-
}
|
|
2099
|
-
};
|
|
2100
|
-
const getOrCreateIsolatedExtensionHostWorker = async (extensionId, absolutePath, workerName = '', contentSecurityPolicy = '', create = createWorker$1, applicationId) => {
|
|
2101
|
-
const application = applicationId === undefined ? undefined : get$7(applicationId);
|
|
2102
|
-
const existingRpc = get$3(extensionId, applicationId);
|
|
2103
|
-
if (existingRpc) {
|
|
2104
|
-
return existingRpc;
|
|
2105
|
-
}
|
|
2106
|
-
const key = JSON.stringify([applicationId ?? null, application?.applicationGeneration ?? null, extensionId]);
|
|
2107
|
-
const pendingRpc = pendingRpcs[key];
|
|
2108
|
-
if (pendingRpc !== undefined) {
|
|
2109
|
-
return pendingRpc;
|
|
2110
|
-
}
|
|
2111
|
-
const newRpc = createAndStoreRpc(extensionId, absolutePath, workerName, contentSecurityPolicy, create, application);
|
|
2112
|
-
pendingRpcs[key] = newRpc;
|
|
2113
|
-
try {
|
|
2114
|
-
return await newRpc;
|
|
2115
|
-
} finally {
|
|
2116
|
-
if (pendingRpcs[key] === newRpc) {
|
|
2117
|
-
delete pendingRpcs[key];
|
|
2118
|
-
}
|
|
2119
|
-
}
|
|
1989
|
+
const sourcePathMarker = '/extension-management-worker/src/';
|
|
1990
|
+
const getExtensionHostSubWorkerUrl = (currentUrl = import.meta.url) => {
|
|
1991
|
+
const relativePath = currentUrl.includes(sourcePathMarker) ? '../../../../extension-host-sub-worker/src/extensionHostSubWorkerMain.js' : '../../extension-host-sub-worker/dist/extensionHostSubWorkerMain.js';
|
|
1992
|
+
return new URL(relativePath, currentUrl).href;
|
|
2120
1993
|
};
|
|
1994
|
+
const extensionHostSubWorkerUrl = getExtensionHostSubWorkerUrl();
|
|
2121
1995
|
|
|
2122
|
-
|
|
2123
|
-
const application = applicationId === undefined ? undefined : get$7(applicationId);
|
|
2124
|
-
const updateStatus = status => {
|
|
2125
|
-
if (applicationId === undefined) {
|
|
2126
|
-
updateRuntimeStatus(extensionId, status);
|
|
2127
|
-
return;
|
|
2128
|
-
}
|
|
2129
|
-
const current = get$7(applicationId);
|
|
2130
|
-
if (current.applicationGeneration !== application?.applicationGeneration) {
|
|
2131
|
-
throw new Error(`Stale extension application: ${applicationId}`);
|
|
2132
|
-
}
|
|
2133
|
-
updateRuntimeStatus(extensionId, status, applicationId);
|
|
2134
|
-
};
|
|
2135
|
-
const startTime = performance.now();
|
|
2136
|
-
updateStatus({
|
|
2137
|
-
activationEvent,
|
|
2138
|
-
activationStartTime: startTime,
|
|
2139
|
-
status: Activating
|
|
2140
|
-
});
|
|
2141
|
-
try {
|
|
2142
|
-
const rpc = applicationId === undefined ? await getOrCreate(extensionId, absolutePath, workerName, contentSecurityPolicy) : await getOrCreate(extensionId, absolutePath, workerName, contentSecurityPolicy, undefined, applicationId);
|
|
2143
|
-
const endTime = performance.now();
|
|
2144
|
-
updateStatus({
|
|
2145
|
-
activationEndTime: endTime,
|
|
2146
|
-
activationTime: endTime - startTime,
|
|
2147
|
-
status: Activated
|
|
2148
|
-
});
|
|
2149
|
-
return rpc;
|
|
2150
|
-
} catch (error) {
|
|
2151
|
-
if (application === undefined || isCurrentApplication(application)) {
|
|
2152
|
-
updateStatus({
|
|
2153
|
-
error: getErrorMessage(error),
|
|
2154
|
-
status: Error$1
|
|
2155
|
-
});
|
|
2156
|
-
}
|
|
2157
|
-
throw error;
|
|
2158
|
-
}
|
|
2159
|
-
};
|
|
1996
|
+
// TODO
|
|
2160
1997
|
|
|
2161
1998
|
const getOrigin = () => {
|
|
2162
1999
|
return globalThis.location?.origin || 'http://localhost';
|
|
@@ -2287,15 +2124,6 @@ const getContentSecurityPolicy = (directives, absolutePath, rpcInfos) => {
|
|
|
2287
2124
|
return `default-src 'none'; script-src ${[...scriptSources].join(' ')}; worker-src 'none'; child-src 'none'; connect-src ${connectDirective};`;
|
|
2288
2125
|
};
|
|
2289
2126
|
|
|
2290
|
-
const sourcePathMarker = '/extension-management-worker/src/';
|
|
2291
|
-
const getExtensionHostSubWorkerUrl = (currentUrl = import.meta.url) => {
|
|
2292
|
-
const relativePath = currentUrl.includes(sourcePathMarker) ? '../../../../extension-host-sub-worker/src/extensionHostSubWorkerMain.js' : '../../extension-host-sub-worker/dist/extensionHostSubWorkerMain.js';
|
|
2293
|
-
return new URL(relativePath, currentUrl).href;
|
|
2294
|
-
};
|
|
2295
|
-
const extensionHostSubWorkerUrl = getExtensionHostSubWorkerUrl();
|
|
2296
|
-
|
|
2297
|
-
// TODO
|
|
2298
|
-
|
|
2299
2127
|
const getUrlPrefix = (platform, extensionPath) => {
|
|
2300
2128
|
if (extensionPath.startsWith('http://') || extensionPath.startsWith('https://')) {
|
|
2301
2129
|
return extensionPath;
|
|
@@ -2318,10 +2146,11 @@ const getServices = application => {
|
|
|
2318
2146
|
let services = applications.get(generation);
|
|
2319
2147
|
if (!services) {
|
|
2320
2148
|
services = {
|
|
2321
|
-
children: new
|
|
2149
|
+
children: new Map(),
|
|
2322
2150
|
declarations: new Map(),
|
|
2151
|
+
extensionVersions: new Map(),
|
|
2323
2152
|
nextChild: 0,
|
|
2324
|
-
ports: new
|
|
2153
|
+
ports: new Map()
|
|
2325
2154
|
};
|
|
2326
2155
|
applications.set(generation, services);
|
|
2327
2156
|
}
|
|
@@ -2339,6 +2168,7 @@ const register = (extension, platform) => {
|
|
|
2339
2168
|
}
|
|
2340
2169
|
services.declarations.set(info.id, {
|
|
2341
2170
|
...info,
|
|
2171
|
+
extensionId: extension.id,
|
|
2342
2172
|
url: `${prefix}/${info.url}`
|
|
2343
2173
|
});
|
|
2344
2174
|
}
|
|
@@ -2348,15 +2178,16 @@ const getRpcInfo$1 = (application, id) => {
|
|
|
2348
2178
|
if (!info) throw new Error(`Rpc not found ${id}`);
|
|
2349
2179
|
return info;
|
|
2350
2180
|
};
|
|
2351
|
-
const createWorker = async (application, info, port, legacy = false) => {
|
|
2181
|
+
const createWorker$1 = async (application, info, port, legacy = false, extensionId) => {
|
|
2352
2182
|
const services = getServices(application);
|
|
2353
2183
|
const id = JSON.stringify([application.applicationId, application.applicationGeneration, 'child', ++services.nextChild]);
|
|
2354
|
-
services.children.
|
|
2184
|
+
services.children.set(id, extensionId);
|
|
2355
2185
|
const url = legacy ? extensionHostSubWorkerUrl : info.url;
|
|
2356
2186
|
try {
|
|
2357
2187
|
const policy = getContentSecurityPolicy(info.contentSecurityPolicy || [], url);
|
|
2358
2188
|
await invokeAndTransfer('LaunchIsolatedExtensionHostWorker.launchIsolatedExtensionHostWorker', port, id, url, info.name || '', policy);
|
|
2359
2189
|
assertCurrentApplication(application);
|
|
2190
|
+
if (!services.children.has(id)) throw new Error('Extension worker was disposed during launch');
|
|
2360
2191
|
} catch (error) {
|
|
2361
2192
|
services.children.delete(id);
|
|
2362
2193
|
await invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id);
|
|
@@ -2364,8 +2195,9 @@ const createWorker = async (application, info, port, legacy = false) => {
|
|
|
2364
2195
|
}
|
|
2365
2196
|
};
|
|
2366
2197
|
const fileSystemMethods = new Set(['readFile', 'readDirWithFileTypes', 'stat', 'exists', 'writeFile', 'mkdir', 'remove', 'rename', 'copy', 'getBlob']);
|
|
2367
|
-
const createFileSystemPort = async (application, port) => {
|
|
2198
|
+
const createFileSystemPort = async (application, port, extensionId) => {
|
|
2368
2199
|
const services = getServices(application);
|
|
2200
|
+
const version = extensionId === undefined ? 0 : services.extensionVersions.get(extensionId) || 0;
|
|
2369
2201
|
const rpc = await create$7({
|
|
2370
2202
|
commandMap: {},
|
|
2371
2203
|
messagePort: port
|
|
@@ -2381,7 +2213,10 @@ const createFileSystemPort = async (application, port) => {
|
|
|
2381
2213
|
};
|
|
2382
2214
|
try {
|
|
2383
2215
|
assertCurrentApplication(application);
|
|
2384
|
-
services.
|
|
2216
|
+
if (extensionId !== undefined && (services.extensionVersions.get(extensionId) || 0) !== version) {
|
|
2217
|
+
throw new Error('Extension was reloaded while opening its filesystem port');
|
|
2218
|
+
}
|
|
2219
|
+
services.ports.set(rpc, extensionId);
|
|
2385
2220
|
} catch (error) {
|
|
2386
2221
|
await rpc.dispose();
|
|
2387
2222
|
throw error;
|
|
@@ -2391,13 +2226,215 @@ const dispose = async application => {
|
|
|
2391
2226
|
const services = applications.get(application.applicationGeneration);
|
|
2392
2227
|
if (!services) return;
|
|
2393
2228
|
applications.delete(application.applicationGeneration);
|
|
2394
|
-
const results = await Promise.allSettled([...Array.from(services.ports, rpc => Promise.try(() => rpc.dispose())), ...Array.from(services.children, id => invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id))]);
|
|
2229
|
+
const results = await Promise.allSettled([...Array.from(services.ports.keys(), rpc => Promise.try(() => rpc.dispose())), ...Array.from(services.children.keys(), id => invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id))]);
|
|
2395
2230
|
services.ports.clear();
|
|
2396
2231
|
services.children.clear();
|
|
2397
2232
|
services.declarations.clear();
|
|
2398
2233
|
const errors = results.filter(result => result.status === 'rejected').map(result => result.reason);
|
|
2399
2234
|
if (errors.length > 0) throw new AggregateError(errors, 'Failed to dispose application services');
|
|
2400
2235
|
};
|
|
2236
|
+
const disposeExtension = async (application, extensionId) => {
|
|
2237
|
+
const services = applications.get(application.applicationGeneration);
|
|
2238
|
+
if (!services) return;
|
|
2239
|
+
services.extensionVersions.set(extensionId, (services.extensionVersions.get(extensionId) || 0) + 1);
|
|
2240
|
+
const ports = [...services.ports].filter(([, owner]) => owner === extensionId).map(([rpc]) => rpc);
|
|
2241
|
+
const children = [...services.children].filter(([, owner]) => owner === extensionId).map(([id]) => id);
|
|
2242
|
+
for (const rpc of ports) services.ports.delete(rpc);
|
|
2243
|
+
for (const id of children) services.children.delete(id);
|
|
2244
|
+
for (const [id, info] of services.declarations) {
|
|
2245
|
+
if (info.extensionId === extensionId) services.declarations.delete(id);
|
|
2246
|
+
}
|
|
2247
|
+
const results = await Promise.allSettled([...ports.map(rpc => Promise.try(() => rpc.dispose())), ...children.map(id => invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', id))]);
|
|
2248
|
+
const errors = results.filter(result => result.status === 'rejected').map(result => result.reason);
|
|
2249
|
+
if (errors.length > 0) throw new AggregateError(errors, `Failed to dispose extension services: ${extensionId}`);
|
|
2250
|
+
};
|
|
2251
|
+
|
|
2252
|
+
const rpcs$1 = Object.create(null);
|
|
2253
|
+
const applicationRpcs = new Map();
|
|
2254
|
+
const get$3 = (extensionId, applicationId) => {
|
|
2255
|
+
if (applicationId !== undefined) {
|
|
2256
|
+
return applicationRpcs.get(applicationId)?.get(extensionId);
|
|
2257
|
+
}
|
|
2258
|
+
return rpcs$1[extensionId];
|
|
2259
|
+
};
|
|
2260
|
+
const getAll = applicationId => {
|
|
2261
|
+
if (applicationId !== undefined) {
|
|
2262
|
+
return [...(applicationRpcs.get(applicationId)?.values() || [])];
|
|
2263
|
+
}
|
|
2264
|
+
return Object.values(rpcs$1);
|
|
2265
|
+
};
|
|
2266
|
+
const getIds = applicationId => {
|
|
2267
|
+
if (applicationId !== undefined) {
|
|
2268
|
+
return [...(applicationRpcs.get(applicationId)?.keys() || [])];
|
|
2269
|
+
}
|
|
2270
|
+
return Object.keys(rpcs$1);
|
|
2271
|
+
};
|
|
2272
|
+
const set$2 = (extensionId, rpc, applicationId) => {
|
|
2273
|
+
if (applicationId !== undefined) {
|
|
2274
|
+
const entries = applicationRpcs.get(applicationId) || new Map();
|
|
2275
|
+
entries.set(extensionId, rpc);
|
|
2276
|
+
applicationRpcs.set(applicationId, entries);
|
|
2277
|
+
return;
|
|
2278
|
+
}
|
|
2279
|
+
rpcs$1[extensionId] = rpc;
|
|
2280
|
+
};
|
|
2281
|
+
const remove$1 = (extensionId, applicationId) => {
|
|
2282
|
+
if (applicationId !== undefined) {
|
|
2283
|
+
const entries = applicationRpcs.get(applicationId);
|
|
2284
|
+
const rpc = entries?.get(extensionId);
|
|
2285
|
+
entries?.delete(extensionId);
|
|
2286
|
+
if (entries?.size === 0) {
|
|
2287
|
+
applicationRpcs.delete(applicationId);
|
|
2288
|
+
}
|
|
2289
|
+
return rpc;
|
|
2290
|
+
}
|
|
2291
|
+
const rpc = rpcs$1[extensionId];
|
|
2292
|
+
delete rpcs$1[extensionId];
|
|
2293
|
+
return rpc;
|
|
2294
|
+
};
|
|
2295
|
+
const clear = applicationId => {
|
|
2296
|
+
if (applicationId !== undefined) {
|
|
2297
|
+
applicationRpcs.delete(applicationId);
|
|
2298
|
+
return;
|
|
2299
|
+
}
|
|
2300
|
+
for (const key of Object.keys(rpcs$1)) {
|
|
2301
|
+
delete rpcs$1[key];
|
|
2302
|
+
}
|
|
2303
|
+
};
|
|
2304
|
+
|
|
2305
|
+
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
2306
|
+
|
|
2307
|
+
const pendingRpcs = Object.create(null);
|
|
2308
|
+
const getPendingExtensionIds = application => {
|
|
2309
|
+
return Object.keys(pendingRpcs).flatMap(key => {
|
|
2310
|
+
const [applicationId, generation, extensionId] = JSON.parse(key);
|
|
2311
|
+
return applicationId === application.applicationId && generation === application.applicationGeneration ? [extensionId] : [];
|
|
2312
|
+
});
|
|
2313
|
+
};
|
|
2314
|
+
const getRuntimeId = (extensionId, application) => {
|
|
2315
|
+
return application?.applicationId === undefined ? extensionId : JSON.stringify([application.applicationId, application.applicationGeneration, extensionId]);
|
|
2316
|
+
};
|
|
2317
|
+
const bindCommandMap = (rpc, commandMap) => {
|
|
2318
|
+
if (rpc.ipc) {
|
|
2319
|
+
rpc.ipc.execute = createExtensionCommandExecutor(commandMap);
|
|
2320
|
+
}
|
|
2321
|
+
return rpc;
|
|
2322
|
+
};
|
|
2323
|
+
const createIsolatedExtensionHostWorker = async (extensionId, absolutePath, workerName, contentSecurityPolicy, createRpc, invokeAndTransfer, application) => {
|
|
2324
|
+
const runtimeId = getRuntimeId(extensionId, application);
|
|
2325
|
+
const invokeCommand = application === undefined ? undefined : (method, ...args) => {
|
|
2326
|
+
assertCurrentApplication(application);
|
|
2327
|
+
if (method === 'Extensions.registerFileChangeHandler') {
|
|
2328
|
+
return register$1(extensionId, application.applicationId);
|
|
2329
|
+
}
|
|
2330
|
+
if (method === 'Extensions.unregisterFileChangeHandler') {
|
|
2331
|
+
return unregister(extensionId, application.applicationId);
|
|
2332
|
+
}
|
|
2333
|
+
if (method === 'Extensions.sendMessagePortToFileSystemWorker') {
|
|
2334
|
+
return createFileSystemPort(application, args[0], extensionId);
|
|
2335
|
+
}
|
|
2336
|
+
if (method === 'Extensions.createWebViewWorkerRpc' || method === 'Extensions.createWebViewWorkerRpc2') {
|
|
2337
|
+
return createWorker$1(application, args[0], args[1], method === 'Extensions.createWebViewWorkerRpc', extensionId);
|
|
2338
|
+
}
|
|
2339
|
+
const invokeApplication = commandMapRef['Extensions.invokeForApplication'];
|
|
2340
|
+
if (!invokeApplication) {
|
|
2341
|
+
throw new Error('Application extension command routing is not initialized');
|
|
2342
|
+
}
|
|
2343
|
+
return invokeApplication(application.applicationId, method, ...args);
|
|
2344
|
+
};
|
|
2345
|
+
const commandMap = createExtensionCommandMap(runtimeId, invokeCommand);
|
|
2346
|
+
const rpc = await createRpc({
|
|
2347
|
+
// PlainMessagePortRpc registers this map process-wide. Bind the restricted
|
|
2348
|
+
// callbacks to this port below, never to the shared host command table.
|
|
2349
|
+
commandMap: {},
|
|
2350
|
+
isMessagePortOpen: true,
|
|
2351
|
+
send(port) {
|
|
2352
|
+
return invokeAndTransfer('LaunchIsolatedExtensionHostWorker.launchIsolatedExtensionHostWorker', port, runtimeId, absolutePath, workerName, contentSecurityPolicy);
|
|
2353
|
+
}
|
|
2354
|
+
});
|
|
2355
|
+
return bindCommandMap(rpc, commandMap);
|
|
2356
|
+
};
|
|
2357
|
+
const createWorker = (extensionId, absolutePath, workerName, contentSecurityPolicy, application) => {
|
|
2358
|
+
return createIsolatedExtensionHostWorker(extensionId, absolutePath, workerName, contentSecurityPolicy, create$6, invokeAndTransfer, application);
|
|
2359
|
+
};
|
|
2360
|
+
const createAndStoreRpc = async (extensionId, absolutePath, workerName, contentSecurityPolicy, create, application) => {
|
|
2361
|
+
try {
|
|
2362
|
+
const rpc = application === undefined ? await create(extensionId, absolutePath, workerName, contentSecurityPolicy) : await create(extensionId, absolutePath, workerName, contentSecurityPolicy, application);
|
|
2363
|
+
if (application !== undefined) {
|
|
2364
|
+
try {
|
|
2365
|
+
assertCurrentApplication(application);
|
|
2366
|
+
} catch (error) {
|
|
2367
|
+
await Promise.allSettled([rpc.dispose(), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
|
|
2368
|
+
throw error;
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
set$2(extensionId, rpc, application?.applicationId);
|
|
2372
|
+
return rpc;
|
|
2373
|
+
} catch (error) {
|
|
2374
|
+
console.error(`[extension-management-worker] ${extensionId} failed to activate`, error);
|
|
2375
|
+
throw error;
|
|
2376
|
+
}
|
|
2377
|
+
};
|
|
2378
|
+
const getOrCreateIsolatedExtensionHostWorker = async (extensionId, absolutePath, workerName = '', contentSecurityPolicy = '', create = createWorker, applicationId) => {
|
|
2379
|
+
const application = applicationId === undefined ? undefined : get$7(applicationId);
|
|
2380
|
+
const existingRpc = get$3(extensionId, applicationId);
|
|
2381
|
+
if (existingRpc) {
|
|
2382
|
+
return existingRpc;
|
|
2383
|
+
}
|
|
2384
|
+
const key = JSON.stringify([applicationId ?? null, application?.applicationGeneration ?? null, extensionId]);
|
|
2385
|
+
const pendingRpc = pendingRpcs[key];
|
|
2386
|
+
if (pendingRpc !== undefined) {
|
|
2387
|
+
return pendingRpc;
|
|
2388
|
+
}
|
|
2389
|
+
const newRpc = createAndStoreRpc(extensionId, absolutePath, workerName, contentSecurityPolicy, create, application);
|
|
2390
|
+
pendingRpcs[key] = newRpc;
|
|
2391
|
+
try {
|
|
2392
|
+
return await newRpc;
|
|
2393
|
+
} finally {
|
|
2394
|
+
if (pendingRpcs[key] === newRpc) {
|
|
2395
|
+
delete pendingRpcs[key];
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
};
|
|
2399
|
+
|
|
2400
|
+
const activateIsolatedExtension = async (extensionId, absolutePath, workerName, contentSecurityPolicy, activationEvent, getOrCreate = getOrCreateIsolatedExtensionHostWorker, applicationId) => {
|
|
2401
|
+
const application = applicationId === undefined ? undefined : get$7(applicationId);
|
|
2402
|
+
const updateStatus = status => {
|
|
2403
|
+
if (applicationId === undefined) {
|
|
2404
|
+
updateRuntimeStatus(extensionId, status);
|
|
2405
|
+
return;
|
|
2406
|
+
}
|
|
2407
|
+
const current = get$7(applicationId);
|
|
2408
|
+
if (current.applicationGeneration !== application?.applicationGeneration) {
|
|
2409
|
+
throw new Error(`Stale extension application: ${applicationId}`);
|
|
2410
|
+
}
|
|
2411
|
+
updateRuntimeStatus(extensionId, status, applicationId);
|
|
2412
|
+
};
|
|
2413
|
+
const startTime = performance.now();
|
|
2414
|
+
updateStatus({
|
|
2415
|
+
activationEvent,
|
|
2416
|
+
activationStartTime: startTime,
|
|
2417
|
+
status: Activating
|
|
2418
|
+
});
|
|
2419
|
+
try {
|
|
2420
|
+
const rpc = applicationId === undefined ? await getOrCreate(extensionId, absolutePath, workerName, contentSecurityPolicy) : await getOrCreate(extensionId, absolutePath, workerName, contentSecurityPolicy, undefined, applicationId);
|
|
2421
|
+
const endTime = performance.now();
|
|
2422
|
+
updateStatus({
|
|
2423
|
+
activationEndTime: endTime,
|
|
2424
|
+
activationTime: endTime - startTime,
|
|
2425
|
+
status: Activated
|
|
2426
|
+
});
|
|
2427
|
+
return rpc;
|
|
2428
|
+
} catch (error) {
|
|
2429
|
+
if (application === undefined || isCurrentApplication(application)) {
|
|
2430
|
+
updateStatus({
|
|
2431
|
+
error: getErrorMessage(error),
|
|
2432
|
+
status: Error$1
|
|
2433
|
+
});
|
|
2434
|
+
}
|
|
2435
|
+
throw error;
|
|
2436
|
+
}
|
|
2437
|
+
};
|
|
2401
2438
|
|
|
2402
2439
|
const rpcs = Object.create(null);
|
|
2403
2440
|
const add = (id, rpc) => {
|
|
@@ -5806,6 +5843,69 @@ const getLanguages = async (platform, assetDir) => {
|
|
|
5806
5843
|
}
|
|
5807
5844
|
};
|
|
5808
5845
|
|
|
5846
|
+
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
5847
|
+
|
|
5848
|
+
const queues = new Map();
|
|
5849
|
+
const replace = async (application, extensionId, extension) => {
|
|
5850
|
+
assertCurrentApplication(application);
|
|
5851
|
+
if (!extension || typeof extension.id !== 'string' || !extension.id || typeof extension.browser !== 'string' || extension.isolated !== true) {
|
|
5852
|
+
throw new Error('Expected an isolated web extension');
|
|
5853
|
+
}
|
|
5854
|
+
const applicationId = application.applicationId;
|
|
5855
|
+
const current = get$7(applicationId);
|
|
5856
|
+
if (current.webExtensions.every(({
|
|
5857
|
+
id
|
|
5858
|
+
}) => id !== extensionId)) {
|
|
5859
|
+
throw new Error(`Application extension not found: ${extensionId}`);
|
|
5860
|
+
}
|
|
5861
|
+
if (extension.id !== extensionId && current.webExtensions.some(({
|
|
5862
|
+
id
|
|
5863
|
+
}) => id === extension.id)) {
|
|
5864
|
+
throw new Error(`Duplicate application extension: ${extension.id}`);
|
|
5865
|
+
}
|
|
5866
|
+
// Finish pending startup before removing its RPC, including failed activations.
|
|
5867
|
+
try {
|
|
5868
|
+
await waitForExtensionActivations(current);
|
|
5869
|
+
} catch {
|
|
5870
|
+
// Failed startup must still allow replacing the broken extension.
|
|
5871
|
+
}
|
|
5872
|
+
assertCurrentApplication(application);
|
|
5873
|
+
const rpc = remove$1(extensionId, applicationId);
|
|
5874
|
+
unregister(extensionId, applicationId);
|
|
5875
|
+
const results = await Promise.allSettled([disposeExtension(application, extensionId), Promise.try(() => rpc?.dispose()), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
|
|
5876
|
+
assertCurrentApplication(application);
|
|
5877
|
+
resetExtensionActivation(extensionId, application);
|
|
5878
|
+
resetExtensionRuntimeState(extensionId, applicationId);
|
|
5879
|
+
const errors = results.filter(result => result.status === 'rejected').map(result => result.reason);
|
|
5880
|
+
if (errors.length > 0) throw new AggregateError(errors, `Failed to reload extension ${extensionId}`);
|
|
5881
|
+
update({
|
|
5882
|
+
cachedExtensions: undefined,
|
|
5883
|
+
webExtensions: get$7(applicationId).webExtensions.map(previous => previous.id === extensionId ? {
|
|
5884
|
+
...extension
|
|
5885
|
+
} : previous)
|
|
5886
|
+
}, applicationId);
|
|
5887
|
+
};
|
|
5888
|
+
const run = async (previous, application, extensionId, extension) => {
|
|
5889
|
+
try {
|
|
5890
|
+
await previous;
|
|
5891
|
+
} catch {
|
|
5892
|
+
// A later save can recover from an earlier reload failure.
|
|
5893
|
+
}
|
|
5894
|
+
await replace(application, extensionId, extension);
|
|
5895
|
+
};
|
|
5896
|
+
const reloadApplicationExtension = async (applicationId, extensionId, extension) => {
|
|
5897
|
+
const application = get$7(applicationId);
|
|
5898
|
+
const key = application.applicationGeneration;
|
|
5899
|
+
const previous = queues.get(key) || Promise.resolve();
|
|
5900
|
+
const operation = run(previous, application, extensionId, extension);
|
|
5901
|
+
queues.set(key, operation);
|
|
5902
|
+
try {
|
|
5903
|
+
await operation;
|
|
5904
|
+
} finally {
|
|
5905
|
+
if (queues.get(key) === operation) queues.delete(key);
|
|
5906
|
+
}
|
|
5907
|
+
};
|
|
5908
|
+
|
|
5809
5909
|
const sendMessagePortToElectron = async (port, initialCommand) => {
|
|
5810
5910
|
await invokeAndTransfer$1('SendMessagePortToElectron.sendMessagePortToElectron', port, initialCommand, EmbedsWorker);
|
|
5811
5911
|
};
|
|
@@ -5872,12 +5972,15 @@ const invokeForApplication = async (applicationId, method, ...args) => {
|
|
|
5872
5972
|
switch (method) {
|
|
5873
5973
|
case 'ExtensionApi.readFile':
|
|
5874
5974
|
return invoke('Application.execute', applicationId, 'FileSystem.readFile', ...args);
|
|
5975
|
+
case 'ExtensionHostQuickPick.showQuickInput':
|
|
5976
|
+
case 'ExtensionHostQuickPick.showQuickPick':
|
|
5977
|
+
return invoke('Application.execute', applicationId, method, ...args);
|
|
5875
5978
|
case 'Extensions.activateByEvent':
|
|
5876
5979
|
return activateByEvent(args[0], args[1], args[2] ?? application.platform, application);
|
|
5877
5980
|
case 'Extensions.createWebViewWorkerRpc':
|
|
5878
|
-
return createWorker(application, args[0], args[1], true);
|
|
5981
|
+
return createWorker$1(application, args[0], args[1], true);
|
|
5879
5982
|
case 'Extensions.createWebViewWorkerRpc2':
|
|
5880
|
-
return createWorker(application, args[0], args[1]);
|
|
5983
|
+
return createWorker$1(application, args[0], args[1]);
|
|
5881
5984
|
case 'Extensions.getAllExtensions':
|
|
5882
5985
|
return getAllExtensionsWithState(application, args[0] || '', args[1] ?? application.platform);
|
|
5883
5986
|
case 'Extensions.getDynamicWebExtensions':
|
|
@@ -5995,6 +6098,7 @@ const commandMap = {
|
|
|
5995
6098
|
'Extensions.invalidateExtensionsCache': invalidateExtensionsCache,
|
|
5996
6099
|
'Extensions.invokeForApplication': invokeForApplication,
|
|
5997
6100
|
'Extensions.readOutputChannel': wrapCommand(readOutputChannel),
|
|
6101
|
+
'Extensions.reloadApplicationExtension': reloadApplicationExtension,
|
|
5998
6102
|
'Extensions.renderViewInstance': renderViewInstance,
|
|
5999
6103
|
'Extensions.requestViewRerender': requestViewRerender,
|
|
6000
6104
|
'Extensions.saveViewInstanceState': saveViewInstanceState,
|