Skip to content

Commit a7b1e06

Browse files
committed
Add support for web worker extensions to define their entry point via "browser"
1 parent 98e653e commit a7b1e06

9 files changed

Lines changed: 39 additions & 20 deletions

File tree

resources/serverless/code-web.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ async function getExtensionPackageJSON(extensionPath) {
154154
}
155155

156156
if (packageJSON.browser) {
157-
packageJSON.main = packageJSON.browser;
158-
159157
let mainFilePath = path.join(extensionPath, packageJSON.browser);
160158
if (path.extname(mainFilePath) !== '.js') {
161159
mainFilePath += '.js';

src/vs/workbench/api/common/extHostExtensionService.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,6 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
193193
}
194194
}
195195

196-
protected abstract _beforeAlmostReadyToRunExtensions(): Promise<void>;
197-
198196
public async deactivateAll(): Promise<void> {
199197
let allPromises: Promise<void>[] = [];
200198
try {
@@ -254,7 +252,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
254252
if (!this._extensionPathIndex) {
255253
const tree = TernarySearchTree.forPaths<IExtensionDescription>();
256254
const extensions = this._registry.getAllExtensionDescriptions().map(ext => {
257-
if (!ext.main) {
255+
if (!this._getEntryPoint(ext)) {
258256
return undefined;
259257
}
260258
return this._hostUtils.realpath(ext.extensionLocation.fsPath).then(value => tree.set(URI.file(value).fsPath, ext));
@@ -345,7 +343,8 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
345343
const event = getTelemetryActivationEvent(extensionDescription, reason);
346344
type ActivatePluginClassification = {} & TelemetryActivationEventFragment;
347345
this._mainThreadTelemetryProxy.$publicLog2<TelemetryActivationEvent, ActivatePluginClassification>('activatePlugin', event);
348-
if (!extensionDescription.main) {
346+
const entryPoint = this._getEntryPoint(extensionDescription);
347+
if (!entryPoint) {
349348
// Treat the extension as being empty => NOT AN ERROR CASE
350349
return Promise.resolve(new EmptyExtension(ExtensionActivationTimes.NONE));
351350
}
@@ -355,15 +354,13 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
355354

356355
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
357356
return Promise.all([
358-
this._loadCommonJSModule<IExtensionModule>(joinPath(extensionDescription.extensionLocation, extensionDescription.main), activationTimesBuilder),
357+
this._loadCommonJSModule<IExtensionModule>(joinPath(extensionDescription.extensionLocation, entryPoint), activationTimesBuilder),
359358
this._loadExtensionContext(extensionDescription)
360359
]).then(values => {
361360
return AbstractExtHostExtensionService._callActivate(this._logService, extensionDescription.identifier, values[0], values[1], activationTimesBuilder);
362361
});
363362
}
364363

365-
protected abstract _loadCommonJSModule<T>(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T>;
366-
367364
private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise<vscode.ExtensionContext> {
368365

369366
const globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage);
@@ -747,6 +744,9 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
747744
this._onDidChangeRemoteConnectionData.fire();
748745
}
749746

747+
protected abstract _beforeAlmostReadyToRunExtensions(): Promise<void>;
748+
protected abstract _getEntryPoint(extensionDescription: IExtensionDescription): string | undefined;
749+
protected abstract _loadCommonJSModule<T>(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T>;
750750
public abstract async $setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
751751
}
752752

src/vs/workbench/api/node/extHostExtensionService.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { ExtHostDownloadService } from 'vs/workbench/api/node/extHostDownloadSer
1313
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
1414
import { URI } from 'vs/base/common/uri';
1515
import { Schemas } from 'vs/base/common/network';
16+
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
1617

1718
class NodeModuleRequireInterceptor extends RequireInterceptor {
1819

@@ -76,6 +77,10 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
7677
};
7778
}
7879

80+
protected _getEntryPoint(extensionDescription: IExtensionDescription): string | undefined {
81+
return extensionDescription.main;
82+
}
83+
7984
protected _loadCommonJSModule<T>(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
8085
if (module.scheme !== Schemas.file) {
8186
throw new Error(`Cannot load URI: '${module}', must be of file-scheme`);

src/vs/workbench/api/worker/extHostExtensionService.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ExtensionActivationTimesBuilder } from 'vs/workbench/api/common/extHost
88
import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
99
import { URI } from 'vs/base/common/uri';
1010
import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor';
11+
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
1112

1213
class WorkerRequireInterceptor extends RequireInterceptor {
1314

@@ -40,6 +41,10 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
4041
await this._fakeModules.install();
4142
}
4243

44+
protected _getEntryPoint(extensionDescription: IExtensionDescription): string | undefined {
45+
return extensionDescription.browser;
46+
}
47+
4348
protected async _loadCommonJSModule<T>(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
4449

4550
module = module.with({ path: ensureSuffix(module.path, '.js') });

src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export class RuntimeExtensionsEditor extends BaseEditor {
157157
this._extensionService.getExtensions().then((extensions) => {
158158
// We only deal with extensions with source code!
159159
this._extensionsDescriptions = extensions.filter((extension) => {
160-
return !!extension.main;
160+
return Boolean(extension.main) || Boolean(extension.browser);
161161
});
162162
this._updateExtensions();
163163
});

src/vs/workbench/contrib/format/browser/formatActionsMultiple.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class DefaultFormatter extends Disposable implements IWorkbenchContribution {
6464
DefaultFormatter.extensionDescriptions.push(nls.localize('nullFormatterDescription', "None"));
6565

6666
for (const extension of extensions) {
67-
if (extension.main) {
67+
if (extension.main || extension.browser) {
6868
DefaultFormatter.extensionIds.push(extension.identifier.value);
6969
DefaultFormatter.extensionDescriptions.push(extension.description || '');
7070
}

src/vs/workbench/services/extensions/common/remoteExtensionHost.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
204204
const [telemetryInfo, remoteInitData] = await Promise.all([this._telemetryService.getTelemetryInfo(), this._initDataProvider.getInitData()]);
205205

206206
// Collect all identifiers for extension ids which can be considered "resolved"
207-
const resolvedExtensions = remoteInitData.allExtensions.filter(extension => !extension.main).map(extension => extension.identifier);
208-
const hostExtensions = remoteInitData.allExtensions.filter(extension => extension.main && extension.api === 'none').map(extension => extension.identifier);
207+
const resolvedExtensions = remoteInitData.allExtensions.filter(extension => !extension.main && !extension.browser).map(extension => extension.identifier);
208+
const hostExtensions = remoteInitData.allExtensions.filter(extension => (extension.main || extension.browser) && extension.api === 'none').map(extension => extension.identifier);
209209
const workspace = this._contextService.getWorkspace();
210210
return {
211211
commit: this._productService.commit,

src/vs/workbench/services/extensions/electron-browser/extensionService.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -706,10 +706,6 @@ function determineRunningLocation(productService: IProductService, configuration
706706
}
707707
if (extensionKind === 'web' && isInstalledLocally && hasLocalWebWorker) {
708708
// web worker extensions run in the local web worker if possible
709-
if (typeof extension.browser !== 'undefined') {
710-
// The "browser" field determines the entry point
711-
(<any>extension).main = extension.browser;
712-
}
713709
return ExtensionRunningLocation.LocalWebWorker;
714710
}
715711
}

src/vs/workbench/services/extensions/node/extensionPoints.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,8 @@ class ExtensionManifestValidator extends ExtensionManifestHandler {
389389
notices.push(nls.localize('extensionDescription.main1', "property `{0}` can be omitted or must be of type `string`", 'main'));
390390
return false;
391391
} else {
392-
let normalizedAbsolutePath = path.join(extensionFolderPath, extensionDescription.main);
393-
394-
if (normalizedAbsolutePath.indexOf(extensionFolderPath)) {
392+
const normalizedAbsolutePath = path.join(extensionFolderPath, extensionDescription.main);
393+
if (!normalizedAbsolutePath.startsWith(extensionFolderPath)) {
395394
notices.push(nls.localize('extensionDescription.main2', "Expected `main` ({0}) to be included inside extension's folder ({1}). This might make the extension non-portable.", normalizedAbsolutePath, extensionFolderPath));
396395
// not a failure case
397396
}
@@ -401,6 +400,22 @@ class ExtensionManifestValidator extends ExtensionManifestHandler {
401400
return false;
402401
}
403402
}
403+
if (typeof extensionDescription.browser !== 'undefined') {
404+
if (typeof extensionDescription.browser !== 'string') {
405+
notices.push(nls.localize('extensionDescription.browser1', "property `{0}` can be omitted or must be of type `string`", 'browser'));
406+
return false;
407+
} else {
408+
const normalizedAbsolutePath = path.join(extensionFolderPath, extensionDescription.browser);
409+
if (!normalizedAbsolutePath.startsWith(extensionFolderPath)) {
410+
notices.push(nls.localize('extensionDescription.browser2', "Expected `browser` ({0}) to be included inside extension's folder ({1}). This might make the extension non-portable.", normalizedAbsolutePath, extensionFolderPath));
411+
// not a failure case
412+
}
413+
}
414+
if (typeof extensionDescription.activationEvents === 'undefined') {
415+
notices.push(nls.localize('extensionDescription.browser3', "properties `{0}` and `{1}` must both be specified or must both be omitted", 'activationEvents', 'browser'));
416+
return false;
417+
}
418+
}
404419
return true;
405420
}
406421

0 commit comments

Comments
 (0)