Skip to content

Commit f170b50

Browse files
committed
1 parent 8e82678 commit f170b50

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

src/vs/platform/instantiation/common/instantiationService.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,15 @@ export class InstantiationService implements IInstantiationService {
183183
}
184184

185185
for (const { data } of roots) {
186-
// create instance and overwrite the service collections
187-
const instance = this._createServiceInstanceWithOwner(data.id, data.desc.ctor, data.desc.staticArguments, data.desc.supportsDelayedInstantiation, data._trace);
188-
this._setServiceInstance(data.id, instance);
186+
// Repeat the check for this still being a service sync descriptor. That's because
187+
// instantiating a dependency might have side-effect and recursively trigger instantiation
188+
// so that some dependencies are now fullfilled already.
189+
const instanceOrDesc = this._getServiceInstanceOrDescriptor(data.id);
190+
if (instanceOrDesc instanceof SyncDescriptor) {
191+
// create instance and overwrite the service collections
192+
const instance = this._createServiceInstanceWithOwner(data.id, data.desc.ctor, data.desc.staticArguments, data.desc.supportsDelayedInstantiation, data._trace);
193+
this._setServiceInstance(data.id, instance);
194+
}
189195
graph.removeNode(data);
190196
}
191197
}

src/vs/platform/instantiation/test/common/instantiationService.test.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as assert from 'assert';
7-
import { createDecorator, optional, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
7+
import { createDecorator, IInstantiationService, optional, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
88
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
99
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
1010
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
@@ -392,4 +392,36 @@ suite('Instantiation Service', () => {
392392

393393
assert.equal(serviceInstanceCount, 1);
394394
});
395+
396+
test('Remote window / integration tests is broken #105562', function () {
397+
398+
const Service1 = createDecorator<any>('service1');
399+
class Service1Impl {
400+
constructor(@IInstantiationService insta: IInstantiationService) {
401+
const c = insta.invokeFunction(accessor => accessor.get(Service2)); // THIS is the recursive call
402+
assert.ok(c);
403+
}
404+
}
405+
const Service2 = createDecorator<any>('service2');
406+
class Service2Impl {
407+
constructor() { }
408+
}
409+
410+
// This service depends on Service1 and Service2 BUT creating Service1 creates Service2 (via recursive invocation)
411+
// and then Servce2 should not be created a second time
412+
const Service21 = createDecorator<any>('service21');
413+
class Service21Impl {
414+
constructor(@Service2 readonly service2: Service2Impl, @Service1 readonly service1: Service1Impl) { }
415+
}
416+
417+
const insta = new InstantiationService(new ServiceCollection(
418+
[Service1, new SyncDescriptor(Service1Impl)],
419+
[Service2, new SyncDescriptor(Service2Impl)],
420+
[Service21, new SyncDescriptor(Service21Impl)],
421+
));
422+
423+
const obj = insta.invokeFunction(accessor => accessor.get(Service21));
424+
assert.ok(obj);
425+
});
426+
395427
});

0 commit comments

Comments
 (0)