Skip to content

Commit c05b9df

Browse files
1 parent 69edda9 commit c05b9df

2 files changed

Lines changed: 175 additions & 30 deletions

File tree

Source/Workbench/Electron/OTELBridge.ts

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -123,37 +123,18 @@ const Flush = (): void => {
123123
};
124124

125125
// Send via fetch (keepalive) to avoid CORS preflight.
126-
// Split into chunks of 20 spans max to stay under the 64KB keepalive limit.
127-
const AllSpans = Payload.resourceSpans[0].scopeSpans[0].spans;
128-
const ChunkSize = 20;
129-
130-
for (let I = 0; I < AllSpans.length; I += ChunkSize) {
131-
const ChunkPayload = {
132-
resourceSpans: [
133-
{
134-
...Payload.resourceSpans[0],
135-
scopeSpans: [
136-
{
137-
...Payload.resourceSpans[0].scopeSpans[0],
138-
spans: AllSpans.slice(I, I + ChunkSize),
139-
},
140-
],
141-
},
142-
],
143-
};
144-
145-
try {
146-
fetch(OTLPEndpoint, {
147-
method: "POST",
148-
body: JSON.stringify(ChunkPayload),
149-
headers: { "Content-Type": "application/json" },
150-
keepalive: true,
151-
}).catch(() => {
152-
CollectorAvailable = false;
153-
});
154-
} catch {
126+
// Send WITHOUT keepalive to avoid the 64KB browser limit.
127+
// Regular fetch has no size restriction. Fire-and-forget.
128+
try {
129+
fetch(OTLPEndpoint, {
130+
method: "POST",
131+
body: JSON.stringify(Payload),
132+
headers: { "Content-Type": "application/json" },
133+
}).catch(() => {
155134
CollectorAvailable = false;
156-
}
135+
});
136+
} catch {
137+
CollectorAvailable = false;
157138
}
158139
};
159140

astro.config.ts

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,170 @@ export default defineConfig({
650650
);
651651
}
652652

653+
// Step 14: Patch extensionsScannerService (node/) to fetch
654+
// extensions from Mountain via IPC instead of reading from disk.
655+
// The webview has no filesystem access, so the scanner can't read
656+
// builtinExtensionsPath. Instead, we override scanSystemExtensions
657+
// to call extensions:getAll via TauriMainProcessService.
658+
try {
659+
const ScannerPath = join(
660+
TargetDir,
661+
"Static/Application/vs/workbench/services/extensions/electron-browser/extensionsScannerService.js",
662+
);
663+
await writeFile(
664+
ScannerPath,
665+
`import { URI } from '../../../../base/common/uri.js';
666+
import { IExtensionsScannerService } from '../../../../platform/extensionManagement/common/extensionsScannerService.js';
667+
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
668+
import { ILogService } from '../../../../platform/log/common/log.js';
669+
import { Emitter } from '../../../../base/common/event.js';
670+
671+
const _t = (Tag, Detail) => { try { performance.mark('land:exthost:' + Tag, Detail ? { detail: Detail } : undefined); } catch {} };
672+
const _w = (...Args) => { try { console.warn('[Land Scanner]', ...Args); } catch {} };
673+
674+
class ExtensionsScannerService {
675+
constructor(logService) {
676+
this._logService = logService;
677+
this.userExtensionsLocation = URI.file('/extensions');
678+
this._onDidChangeCache = new Emitter();
679+
this.onDidChangeCache = this._onDidChangeCache.event;
680+
_t('scanner:construct');
681+
_w('Constructed');
682+
}
683+
684+
async _fetchFromMountain() {
685+
_t('scanner:fetch:start');
686+
try {
687+
const Invoke = globalThis.__TAURI__?.core?.invoke ?? globalThis.__TAURI__?.invoke;
688+
if (typeof Invoke !== 'function') {
689+
_t('scanner:fetch:no-tauri');
690+
_w('No Tauri invoke available');
691+
return [];
692+
}
693+
const RawResult = await Invoke('MountainIPCInvoke', {
694+
method: 'extensions:getAll',
695+
params: [],
696+
});
697+
const Extensions = Array.isArray(RawResult) ? RawResult : [];
698+
_t('scanner:fetch:result', { count: Extensions.length, type: typeof RawResult, isArray: Array.isArray(RawResult) });
699+
_w('IPC returned', Extensions.length, 'extensions');
700+
if (Extensions.length === 0) return [];
701+
702+
const Mapped = [];
703+
let Errors = 0;
704+
for (let I = 0; I < Extensions.length; I++) {
705+
const ext = Extensions[I];
706+
try {
707+
const location = ext.extensionLocation
708+
? (typeof ext.extensionLocation === 'string' ? URI.parse(ext.extensionLocation) : URI.revive(ext.extensionLocation))
709+
: URI.file('/extensions/' + (ext.name || 'unknown'));
710+
const id = ext.identifier?.value
711+
|| (ext.publisher ? ext.publisher + '.' + ext.name : ext.name)
712+
|| 'unknown';
713+
Mapped.push({
714+
type: 0,
715+
identifier: { id },
716+
manifest: {
717+
name: ext.name || '',
718+
publisher: ext.publisher || '',
719+
version: ext.version || '0.0.0',
720+
engines: ext.engines || { vscode: '*' },
721+
main: ext.main || undefined,
722+
browser: ext.browser || undefined,
723+
activationEvents: ext.activationEvents || [],
724+
contributes: ext.contributes || {},
725+
extensionDependencies: [],
726+
extensionPack: [],
727+
enabledApiProposals: [],
728+
},
729+
location,
730+
isBuiltin: true,
731+
targetPlatform: 'undefined',
732+
isValid: true,
733+
validationMessages: [],
734+
});
735+
} catch (e) {
736+
Errors++;
737+
if (Errors <= 3) _w('Map error for ext', I, ':', String(e).slice(0, 100));
738+
}
739+
}
740+
_t('scanner:fetch:mapped', { mapped: Mapped.length, errors: Errors });
741+
_w('Mapped', Mapped.length, 'extensions,', Errors, 'errors');
742+
if (Mapped.length > 0) {
743+
_w('First:', Mapped[0].identifier.id, 'name:', Mapped[0].manifest.name, 'pub:', Mapped[0].manifest.publisher, 'loc:', Mapped[0].location?.toString?.()?.slice(0, 80));
744+
}
745+
return Mapped;
746+
} catch (e) {
747+
_t('scanner:fetch:error', { message: String(e).slice(0, 200) });
748+
_w('Fetch error:', String(e).slice(0, 200));
749+
return [];
750+
}
751+
}
752+
753+
async scanAllExtensions(systemScanOptions, userScanOptions) {
754+
_t('scanner:scanAll:start');
755+
const sys = await this.scanSystemExtensions(systemScanOptions);
756+
const usr = await this.scanUserExtensions(userScanOptions);
757+
const all = [...sys, ...usr];
758+
_t('scanner:scanAll:done', { system: sys.length, user: usr.length, total: all.length });
759+
_w('scanAll:', sys.length, 'system +', usr.length, 'user =', all.length);
760+
return all;
761+
}
762+
763+
async scanSystemExtensions(scanOptions) {
764+
_t('scanner:scanSystem:start');
765+
const result = await this._fetchFromMountain();
766+
_t('scanner:scanSystem:done', { count: result.length });
767+
_w('scanSystemExtensions returning', result.length);
768+
return result;
769+
}
770+
771+
async scanUserExtensions(scanOptions) {
772+
_t('scanner:scanUser:start');
773+
_w('scanUserExtensions returning 0');
774+
return [];
775+
}
776+
777+
getTargetPlatform() { return Promise.resolve('undefined'); }
778+
getProductVersion() { return { version: '0.0.1', date: undefined }; }
779+
async scanAllUserExtensions(scanOptions) { return []; }
780+
async scanExtensionsUnderDevelopment(existingExtensions, scanOptions) { _t('scanner:scanDev'); return []; }
781+
async scanExistingExtension(extensionLocation, extensionType, scanOptions) { return null; }
782+
async scanOneOrMultipleExtensions(extensionLocation, extensionType, scanOptions) { return []; }
783+
async scanMetadata(extensionLocation) { return undefined; }
784+
async updateMetadata(extensionLocation, metadata) { return undefined; }
785+
async initializeDefaultProfileExtensions() { _t('scanner:initDefaults'); }
786+
}
787+
788+
// DI decorators must be defined before use
789+
var __decorate = function(decorators, target, key, desc) {
790+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
791+
if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function') r = Reflect.decorate(decorators, target, key, desc);
792+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
793+
return c > 3 && r && Object.defineProperty(target, key, r), r;
794+
};
795+
var __param = function(paramIndex, decorator) {
796+
return function(target, key) { decorator(target, key, paramIndex); };
797+
};
798+
ExtensionsScannerService = __decorate([
799+
__param(0, ILogService)
800+
], ExtensionsScannerService);
801+
802+
registerSingleton(IExtensionsScannerService, ExtensionsScannerService, InstantiationType.Delayed);
803+
export { ExtensionsScannerService, IExtensionsScannerService };
804+
`,
805+
"utf-8",
806+
);
807+
console.log(
808+
"[CopyVSCode] Step 14: Patched extensionsScannerService (IPC override)",
809+
);
810+
} catch (Error) {
811+
console.warn(
812+
"[CopyVSCode] Step 14: extensionsScannerService patch failed:",
813+
Error,
814+
);
815+
}
816+
653817
StepMark("done");
654818
console.log("[CopyVSCode] ✓ Assets ready in Target/");
655819

0 commit comments

Comments
 (0)