================================================================
1EJKIS2: CLIM:K8ALL - Image always saved to local drive
PROBLEM DESCRIPTION

VM Stamp:   VM Timestamp: 4.0,(NC) 7/21/97


Problem Information:

Short Description:
Customer moves image and ini file to lan drive, and starts product with  -i
option.  When saving image, he is prompted to save in current directory,
not where the image was originally started from.  This is changed from V3.x.

It looks like System loadedImageFileName which goes to the VM is only
returning the filename.

Steps to Replicate:
see above

Results/Walkback:

Expected Results:

Workaround:
use saveAs

Notes:

================================================================
1EIQUM5: EP:K8NT - IC's load and unload too slowly.

DESCRIPTION:

Product Code(s)   :   VisualAge for Smalltalk, Professional for Windows, V4.02
   (C) Copyright IBM Corporation, 1994, 1997.
   (C) Copyright Object Technology International Inc., 1990, 1997.
VM Timestamp      :   All Rights Reserved.  -  VM Timestamp: 4.0,(NC) 6/30/97
   Image Built: 07/30/97
Client Platform(s):   NT4.0
Server Platform(s):   NT4.0

Description:
		IC's load and unload too slowly.  (See attached document below with
tests comparing SLL's and IC's that were
made by Harvey Gunther of IBM.  ) Customer indicates that IC's don't meet up
with marketing claims that they heard of IC's
working like SLL's.

The customer wants to see IC's that contain approximately 10 - 20 classes load
in less than one second.  They expect to be
required to manage IC runtime prerequisites, loading and unloading manually.
They do not expect IC's to have any intelligence
regarding prerequisite IC's.  They essentially want a fast, lightweight,
"dumb"
IC.


Steps to Recreate:
Workload
A simple class, "THING",  with three methods. I created two samples: 1. THING
as a Smalltalk class; 2. THING as a VisualAge non-visual part. I filed-in the
Smalltalk THING into VisualSmalltalk 3.0.1 for Win32. I compared the results.
I
packaged both THING as a reusable IC in VAST and as a SLL in VisualSmalltalk.
The high level results of System loadComponent:in VAST  and System bind: in
VisualSmalltalk in a development image (I didn't run a runtime inage
comparison) were as follows:

THING as VAST Smalltalk Class:  6800 milliseconds
THING as VAST Non-visual Part:  13700 milliseconds
THING as VSmTk SLL:  863 milliseonds

THING as a VAST Smalltalk class is comparable to THING as a VSmTk SLL  and
both
are comparable to First Union's workload. First Union uses VSmTk classes with
WindowBuilder Pro. They do not use the PARTs Workbench and they do not plan on
using VisualAge parts.

Workload Comparisons:

THING as a VAST Smalltalk class had only KERNEL as a pre-requisite. THING as a
VAST VisualAge non-visual part had all of the prerequisite that were default
for reusable ICs, "DEFAULT" ICs.

Profile of IC Explicit LoadComponent Time:

To help me understand the performance problem of System LoadComponent: (IC
explicit runtime loading). I put some profiling hooks in the method: I made
the
following subdivisions:

1. Primitive Time (Including Disk I/O) - OTI "Black Box", "VMprLoadComponent"
2. Active Symbol and Active Atom Table Resolution.
3.  Namespace Resolution -- "self linkComponent"
4. Image Resolution (Runtime vs. Development Image, menus etc.)

Results
THING as VAST Smalltalk Class                  THING as VAST Non-visual Part

Primitive Time (I/O)					1812 ms (26.6%)		1973  ms (14.4%)
Symbol and Atom Table		4627 ms (68%)			4907 ms (35.9%)
NameSpace								90  ms (1.3%)				6549 ms (47.1%)
Image Time								271 ms (3.9%)				361 ms (2.5%)



Conclusions

The Primitive time including DISK I/O took 2000 milliseconds. This time was
close to uniform across all samples without regard to the number of pre-reqs.
This compares to 863 milliseconds overall for Digitalk.
The only aspect of the problem affected by the number of pre-reqs is the
NameSpace resolution and this would only be a factor for VisualAge not
Smalltalk.

Workaround (if known):
		[NONE]

Special Instructions:
		[Todd Britton will also be working with OTI development on this one]

NOTES:

PDS (10/22/97 8:53:37 AM)
	There are runtime options that can be used to improve the speed of loading ICs (see below).
	I suggest using: runtimeFlags=13

Runtime Options
--------------------------

ICs are broken into parts which can be optionally loaded. The optional parts are:

- (1) ENVY/Manager file pointers for compiled methods.
- (2) Classes and selector information for compiled methods.
- (4) ENVY/Manager category information.
- (8) ENVY/Manager Application associations, shared pool names, class timeStamps, Application
	extended and undefined classes collections, configuration expressions, Application privileges
	and dependent Application collections.

If the command line option '-r' is used when invoking the VM, none of the optional parts are loaded.
Runtime flags can also be specified in the .INI file to control which parts get loaded. Use the number
before each part to exclude that part, add the numbers to exclude multiple parts. The following
example is equivalent to the '-r' command line option.

[VM Options]
runtimeFlags=15

PDS (11/04/97 11:29:19 AM) - 
	Temporary fix for faster loading and removing in: 1EK8NXV: EP:K8 - FIX - faster IC loading and removing

PDS (12/12/97 9:44:11 AM)
	Additional temporary fix to speed up removing in: 1EL47TI: EP:K8 - faster IC removing

	A new API has been added, EmSystemConfiguration >> #removeComponent:checkInstances:. When checkInstances
	is true, a component will fail to remove if there are instances of classes in the component. When checkInstances is
	false, a component will be removed even if there are instances of classes in the component. Note that checking
	instances when removing components increases the time to remove the component.

================================================================

1EK8NXV: EP:K8 - FIX - faster IC loading and removing

	Product:	ENVY/Smalltalk R4.0 MD3
	Problem:
		ICs load and unload too slowly.

	Trigger:	 <1EIQUM5>
	Prereqs:	<none>

	Temporary Fix:
		File-in the following code.


Core becomeDefault!

!EmSystemConfiguration publicMethods !

loadComponent: fileName

	| info names |

	(info := self loadComponentPrimitive: fileName nullTerminated) isNil
		ifTrue: [^nil].

	((self runtimeFlags bitAnd: EsRuntimeNoApplications) == 0 and: [self cannotLoadComponents: info]) ifTrue: [
		names := OrderedCollection new.
		1 to: info size do: [:k | names add: ((info at: k) at: 13)].
		info := nil.
		self globalGarbageCollect.
		names do: [:name | self removeComponentPrimitive: name nullTerminated].
		^false].

	[
		info do: [:extensions |
			| old new element |
			Symbol addTable: (extensions at: 5).
			(extensions at: 5) notNil ifTrue: [
				old := OrderedCollection new.
				new := OrderedCollection new.
				(extensions at: 5) do: [:newSymbol |
					(Symbol symbolTable activeSet includes: newSymbol) ifTrue: [
						element := Symbol symbolTable activeSet at: newSymbol.
						element ~~ newSymbol ifTrue: [
							old add: element.
							new add: newSymbol.
						].
					]].
				old notEmpty ifTrue: [old asArray multiBecome: new asArray].
			].
			EsAtom addTable: (extensions at: 10).
			(extensions at: 10) notNil ifTrue: [
				old := OrderedCollection new.
				new := OrderedCollection new.
				(extensions at: 10) do: [:newAtom |
					(EsAtom atomTable activeSet includes: newAtom) ifTrue: [
						element := EsAtom atomTable activeSet at: newAtom.
						element ~~ newAtom ifTrue: [
							old add: element.
							new add: newAtom.
						].
					]].
				old notEmpty ifTrue: [old asArray multiBecome: new asArray].
			].
		].

		self linkComponents: info.
	] critical.

	self startUpClass loadComponents: info.

	info do: [:extensions |
		(extensions at: 12) notNil ifTrue: [
			(extensions at: 12) send]].

	^true! !

!EmSystemConfiguration privateMethods !

linkComponents: anArray

	| startClass |

	anArray do: [:extensions |
		| element namespace |
		1 to: (element := extensions at: 1) size by: 3 do: [:index |
			(element at: index) instVarAt: (element at: index + 1) put: (element at: index + 2)].
		(extensions at: 2) do: [:cl |
		 	cl superclass == nil ifFalse: [
				cl superclass addSubclass: cl]].
		(extensions at: 3) allNamespaceNames do: [:spacename |
			namespace := Smalltalk createNamespace: spacename.
			((extensions at: 3) namespaceAt: spacename) associationsDo: [:assoc |
				namespace add: assoc]].
		(extensions at: 3) unmanagedNamespace associationsDo: [:assoc | Smalltalk add: assoc].
		1 to: (element := extensions at: 4) size by: 2 do: [:i |
			| libraryIndex |
			libraryIndex := PlatformLibrary libraryIndex: (element at: i).
			(element at: i + 1) do: [:function | function libraryIndex: libraryIndex]].
		1 to: (element := extensions at: 15) size by: 2 do: [:i |
			self setSubsystemType: (element at: i) to: (element at: i + 1).
		].
		(self runtimeFlags bitAnd: EsRuntimeNoApplications) == 0 ifTrue: [
			(extensions at: 7) do: [:app |
				app prerequisites do: [:prereq | prereq addDependentApplication: app]].
			self loadedApplicationsHaveChanged.
		] ifFalse: [
			self loadedSubApplications: self loadedSubApplications, (extensions at: 6).
			self loadedApplications: self loadedApplications, (extensions at: 7).
		].
		1 to: (element := extensions at: 11) size by: 4 do: [:i |
			| class md apps methods categories recompute |
			recompute := false.
			class := (element at: i) isMetaclass
				ifTrue: [(element at: i) primaryInstance]
				ifFalse: [element at: i].
			md := (element at: i) methodDictionary cacheFromClass.
			apps := element at: i + 1.
			categories := element at: i + 2.
			1 to: (methods := element at: i + 3) size by: 2 do: [:j |
				| cats |
				(methods at: j) = #at: ifTrue: [recompute := true].
				md at: (methods at: j) put: (methods at: j + 1).
				apps notNil ifTrue: [
					(self runtimeFlags bitAnd: EsRuntimeNoApplications) == 0 ifTrue: [
						class addApplication: (apps at: j + 1 // 2).
						(element at: i) applicationFor: (methods at: j) is: (apps at: j + 1 // 2).
					].
					(self runtimeFlags bitAnd: EsRuntimeNoCategories) == 0 ifTrue: [
						cats := (categories at: j + 1 // 2) isString
							ifTrue: [Array with: (categories at: j + 1 // 2)]
							ifFalse: [categories at: j + 1 // 2].
						(element at: i) info categorizeSelectors: (Array with: (methods at: j)) in: cats.
					].
				].
			].
			(element at: i) methodsArray: md methodsArray.
			recompute ifTrue: [(element at: i) recomputeSpecialMethods].
			md flushCache.
		].

		(extensions at: 8) do: [:classes |
			classes do: [:cl | (cl respondsTo: #initializeAfterLoad) ifTrue: [cl initializeAfterLoad]]].
		(extensions at: 6) do: [:app | (app respondsTo: #loaded) ifTrue: [app loaded]].
		(extensions at: 9) notNil ifTrue: [startClass := extensions at: 9].
	].

	^startClass
!

removeComponentsFromImage: struct

	 | classes apps prereqs updateTranscriptMenus names done toRemove family |

	##PR = ##'1EBC64P'.

	 classes := (struct at: 2) asSet.
	 prereqs := OrderedCollection new.
	 apps := classes select: [:class |
		  (class notNil and: [class superclass == Application and: [class defined notNil]]) ifTrue: [
			   prereqs add: (Array with: class with: class prerequisites)].
		  (class notNil and: [class superclass == Application or: [class superclass == SubApplication]]) and: [class defined notNil]].

	 (self runtimeFlags bitAnd: EsRuntimeNoApplications) == 0 ifTrue: [
		  "In a development image there could be additional SubApplications and classes."
		  apps copy do: [:app | apps addAll: app allSubApplications].
		  apps do: [:app |
			   classes addAll: app defined.
			   app isApplication ifTrue: [
					 app dependentApplications do: [:dependentApp |
						 (apps includes: dependentApp) ifFalse: [^false]]]].
	 ].

	 classes  do: [:cl |
		  cl subclasses do: [:subclass |
			   (classes includes: subclass) ifFalse: [^false]]].

	 updateTranscriptMenus :=
		  (self respondsTo: #updateTranscriptMenus) and: [
			   (apps detect: [:appOrSub |
					(appOrSub withAllSubApplications detect: [:sub |
						 (self transcriptMenuBuildSelectors
							  detect: [:sel | sub class includesSelector: sel]
							  ifNone: [nil]) notNil]
					ifNone: []) notNil]
			   ifNone: []) notNil].

	 toRemove := OrderedCollection new.
	 family := OrderedCollection new.
	 self loadedSubApplications do: [:app |
		  (app isApplication and: [family notEmpty]) ifTrue: [
			   toRemove add: family.
			   family := OrderedCollection new.
		  ].
		  (apps includes: app) ifTrue: [family add: app].
	 ].
	 family notEmpty ifTrue: [toRemove add: family].
	 toRemove reverseDo: [:c | c do: [:app | (app respondsTo: #removing) ifTrue: [app removing]]].

	 classes asArray multiAllInstances notEmpty ifTrue: [
		  toRemove do: [:c | c do: [:app | (app respondsTo: #failedRemove) ifTrue: [app failedRemove]]].
		  ^false].

	 self loadedApplications: (self loadedApplications reject: [:app | apps includes: app]).
	 self loadedSubApplications: (self loadedSubApplications reject: [:app | apps includes: app]).

	 names := OrderedCollection new.
	 apps do: [:app |
		  app isApplication ifTrue: [names add: app symbol].
		  app isSubApplication ifTrue: [
			   app parent primitiveSubApplications: (app parent subApplications copyWithout: app)].
		  (self runtimeFlags bitAnd: EsRuntimeNoApplications) == 0 ifTrue: [
			   app extended do: [:cl |
					| assoc |
					(assoc := cl applicationAssocAt: app) notNil ifTrue: [
						 cl deleteAllSelectors: assoc value.
						 cl applicationAssocs: (cl applicationAssocs copyWithout: assoc)].
					(assoc := cl class applicationAssocAt: app) notNil ifTrue: [
						 cl class deleteAllSelectors: assoc value.
						 cl class applicationAssocs: (cl class applicationAssocs copyWithout: assoc)].
			   ].
		  ].
	 ].

	 done := Set new.
	 classes do: [:cl |
		  ((done includes: cl) not and: [cl isClass]) ifTrue: [
			   cl withAllSubclasses reverseDo: [:class |
					self removeClassNamed: class symbol from: self globalNamespace.
					done add: class]]].

	 names do: [:symbol | self globalNamespace removeNamespace: symbol].

	 Object withAllSubclassesDo: [:cl |
		  | i removing index j remove selectors |
		  (cl methodsArray class == EsMethodArray and: [cl methodsArray isReadOnly not]) ifTrue: [
			   i := 2.
			   [i <= cl methodsArray size] whileTrue: [
					(index := cl methodsArray at: i) isInteger ifTrue: [
						 j := 1.
						 remove := false.
						 [j < (struct at: 1) size] whileTrue: [
							  (index >= ((struct at: 1) at: j) and: [
								   index < ((struct at: 1) at: j+1)]) ifTrue: [
										remove := true.
										j := (struct at: 1) size.
							  ].
							  j := j + 2.
						 ].
						 remove ifTrue: [
							  removing isNil ifTrue: [
								removing := Set new.
								selectors := Set new.
							  ].
							  removing add: i - 1.
							  selectors add: (cl methodsArray at: i - 1).
						 ].
					].
					i := i + 2.
			   ].
			   removing notNil ifTrue: [
					cl methodDictionary rebuildMethodsArrayWithout: removing; flushCache].

			   "Remove the selectors and any categories which are now empty."
			   selectors notNil ifTrue: [
					(cl info deleteSelectors: selectors) do: [:category |
						 (cl info isCategoryEmpty: category) ifTrue: [
							  cl info removeCategory: category]]].
		  ].
	 ].

	 (self runtimeFlags bitAnd: EsRuntimeNoApplications) == 0 ifTrue: [
		  apps do: [:app |
			   app == self defaultApplication ifTrue: [
					"Removing the image's default application.  Appoint #defaultApplication
					 to worry about appointing a successor."
					self defaultApplication: nil]].
		  prereqs do: [:array |
			   | app |
			   app := array first.
			   array last do: [:prereq |
					prereq isRemoved ifFalse: [prereq removeDependentApplication: app]]].
	 ].

	 (struct at: 3) do: [:assoc | self globalNamespace removeKey: assoc key ifAbsent: []].

	 self callDeferredCallbacks.

	 updateTranscriptMenus ifTrue: [self updateTranscriptMenus].

	 ^true ! !

!EsMBADictionary privateMethods !

cacheFromClass

	methodsArray := self methodsArray isReadOnly
		ifTrue: [self methodsArray copy]
		ifFalse: [self methodsArray].
	methodClass := nil.
! !

EsMBADictionary categoriesFor: #cacheFromClass are: #('ES-Internal')!

================================================================
1EL47TI: EP:K8 - faster IC removing

	Product:	ENVY/Smalltalk R4.0 MD3
	Problem:
		ICs unload too slowly.

	Trigger:	 <1EIQUM5>
	Prereqs:	<1EK8NXV, 1ELGXM1>

	Temporary Fix:
		File-in the following code.

Core becomeDefault!

!EmSystemConfiguration publicMethods !

removeComponent: fileName

	"Remove the image component specified by fileName and all dependent image components
	 from the image. Fail if there are any instances of the classes in the image components. Answer
	 true if the image component was removed, false if the image component failed to remove and
	 nil if the image component does not exist."

	^self removeComponent: fileName checkInstances: true!

removeComponent: fileName checkInstances: checkInstances

	"Remove the image component specified by fileName and all dependent image components
	 from the image. When checkInstances is true, fail if there are any instances of the classes in
	 the image components. Answer true if the image component was removed, false if the image
	 component failed to remove and nil if the image component does not exist."

	| struct unique symbols atoms |
	(struct := self removingComponentPrimitive: fileName nullTerminated) isNil
		ifTrue: [^nil].
	[
		(self removeComponentsFromImage: struct checkInstances: checkInstances) ifFalse: [^false].

		symbols := (struct at: 4) collect: [:set | Symbol symbolTable sets indexOf: set].
		atoms := (struct at: 5) collect: [:set | EsAtom atomTable sets indexOf: set].

		(unique := self removeComponentPrimitive: fileName nullTerminated) isNil ifTrue: [
			struct := self removingComponentPrimitive: fileName nullTerminated.
			symbols with: (struct at: 4) do: [:index :table |
				index > 0 ifTrue: [Symbol symbolTable sets at: index put: table]].
			atoms with: (struct at: 5) do: [:index :table |
				index > 0 ifTrue: [EsAtom atomTable sets at: index put: table]].
			^false].

		symbols asSortedCollection reverseDo: [:index |
			index > 0 ifTrue: [Symbol symbolTable sets removeAtIndex: index]].
		atoms asSortedCollection reverseDo: [:index |
			index > 0 ifTrue: [EsAtom atomTable sets removeAtIndex: index]].

		unique first do: [:symbol | Symbol symbolTable add: symbol].
		unique last do: [:atom | EsAtom atomTable add: atom].
	] critical.

	^true! !

!EmSystemConfiguration privateMethods !

removeComponentsFromImage: struct checkInstances: checkInstances

	| classes apps prereqs updateTranscriptMenus names done toRemove family |

	classes := (struct at: 2) asSet.
	prereqs := OrderedCollection new.
	apps := classes select: [:class |
		(class notNil and: [class superclass == Application and: [class defined notNil]]) ifTrue: [
			prereqs add: (Array with: class with: class prerequisites)].
		(class notNil and: [class superclass == Application or: [class superclass == SubApplication]]) and: [class defined notNil]].

	(self runtimeFlags bitAnd: EsRuntimeNoApplications) == 0 ifTrue: [
		"In a development image there could be additional SubApplications and classes."
		apps copy do: [:app | apps addAll: app allSubApplications].
		apps do: [:app |
			classes addAll: app defined.
			app isApplication ifTrue: [
				app dependentApplications do: [:dependentApp |
					(apps includes: dependentApp) ifFalse: [^false]]]].
	].

	classes  do: [:cl |
		cl subclasses do: [:subclass |
			(classes includes: subclass) ifFalse: [^false]]].

	updateTranscriptMenus :=
		(self respondsTo: #updateTranscriptMenus) and: [
			(apps detect: [:appOrSub |
				(appOrSub withAllSubApplications detect: [:sub |
					(self transcriptMenuBuildSelectors
						detect: [:sel | sub class includesSelector: sel]
						ifNone: [nil]) notNil]
				ifNone: []) notNil]
			ifNone: []) notNil].

	toRemove := OrderedCollection new.
	family := OrderedCollection new.
	self loadedSubApplications do: [:app |
		(app isApplication and: [family notEmpty]) ifTrue: [
			toRemove add: family.
			family := OrderedCollection new.
		].
		(apps includes: app) ifTrue: [family add: app].
	].
	family notEmpty ifTrue: [toRemove add: family].
	toRemove reverseDo: [:c | c do: [:app | (app respondsTo: #removing) ifTrue: [app removing]]].

	checkInstances ifTrue: [
		classes asArray multiAllInstances notEmpty ifTrue: [
			toRemove do: [:c | c do: [:app | (app respondsTo: #failedRemove) ifTrue: [app failedRemove]]].
			^false].
	].

	self loadedApplications: (self loadedApplications reject: [:app | apps includes: app]).
	self loadedSubApplications: (self loadedSubApplications reject: [:app | apps includes: app]).

	names := OrderedCollection new.
	apps do: [:app |
		app isApplication ifTrue: [names add: app symbol].
		app isSubApplication ifTrue: [
			app parent primitiveSubApplications: (app parent subApplications copyWithout: app)].
		(self runtimeFlags bitAnd: EsRuntimeNoApplications) == 0 ifTrue: [
			app extended do: [:cl |
				| assoc |
				(assoc := cl applicationAssocAt: app) notNil ifTrue: [
					cl deleteAllSelectors: assoc value.
					(cl info deleteSelectors: assoc value) do: [:category |
						(cl info isCategoryEmpty: category) ifTrue: [
							cl info removeCategory: category]].
					cl applicationAssocs: (cl applicationAssocs copyWithout: assoc)].
				(assoc := cl class applicationAssocAt: app) notNil ifTrue: [
					cl class deleteAllSelectors: assoc value.
					(cl class info deleteSelectors: assoc value) do: [:category |
						(cl class info isCategoryEmpty: category) ifTrue: [
							cl class info removeCategory: category]].
					cl class applicationAssocs: (cl class applicationAssocs copyWithout: assoc)].
			].
		].
	].

	done := Set new.
	classes do: [:cl |
		((done includes: cl) not and: [cl isClass]) ifTrue: [
			cl withAllSubclasses reverseDo: [:class |
				self removeClassNamed: class symbol from: self globalNamespace flush: false.
				done add: class]]].
	"Flush all caches."
	self class methodDictionary flushCache.

	names do: [:symbol | self globalNamespace removeNamespace: symbol].

	Object withAllSubclassesDo: [:cl |
		| i removing index j remove selectors |
		(cl methodsArray class == EsMethodArray and: [cl methodsArray isReadOnly not]) ifTrue: [
			i := 2.
			[i <= cl methodsArray size] whileTrue: [
				(index := cl methodsArray at: i) isInteger ifTrue: [
					j := 1.
					remove := false.
					[j < (struct at: 1) size] whileTrue: [
						(index >= ((struct at: 1) at: j) and: [
							index < ((struct at: 1) at: j+1)]) ifTrue: [
								remove := true.
								j := (struct at: 1) size.
							].
						j := j + 2.
					].
					remove ifTrue: [
						removing isNil ifTrue: [
							removing := Set new.
							selectors := Set new.
						].
						removing add: i - 1.
						selectors add: (cl methodsArray at: i - 1).
					].
				].
				i := i + 2.
			].
			removing notNil ifTrue: [
				cl methodDictionary rebuildMethodsArrayWithout: removing].

			"Remove the selectors and any categories which are now empty."
			selectors notNil ifTrue: [
				(cl info deleteSelectors: selectors) do: [:category |
					(cl info isCategoryEmpty: category) ifTrue: [
						cl info removeCategory: category]]].
		].
	].
	"Flush all caches."
	self class methodDictionary flushCache.

	(self runtimeFlags bitAnd: EsRuntimeNoApplications) == 0 ifTrue: [
		apps do: [:app |
			app == self defaultApplication ifTrue: [
				"Removing the image's default application.  Appoint #defaultApplication
				 to worry about appointing a successor."
				self defaultApplication: nil]].
		prereqs do: [:array |
			| app |
			app := array first.
			array last do: [:prereq |
				prereq isRemoved ifFalse: [prereq removeDependentApplication: app]]].
	].

	(struct at: 3) do: [:assoc | self globalNamespace removeKey: assoc key ifAbsent: []].

	self callDeferredCallbacks.

	updateTranscriptMenus ifTrue: [self updateTranscriptMenus].

	^true ! !

EmSystemConfiguration categoriesFor: #removeComponent: are: #('ES-API')!
EmSystemConfiguration categoriesFor: #removeComponent:checkInstances: are: #('ES-API')!
EmSystemConfiguration categoriesFor: #removeComponentsFromImage:checkInstances: are: #('ES-Internal')!

EmImageSupportES becomeDefault!

!EmSystemConfiguration publicMethods !

removeClassNamed: aName from: environment flush: flush
	"Remove the class named aName from @environment.
	 Answer the class. The instances if any are still valid
	 and will continue to run."

	| removedClass result controllerName |
	removedClass := environment classAt: aName.
	controllerName := removedClass controller name.
	result := environment removeClassNamed: aName.
	result == nil ifFalse: [
		removedClass wasRemoved: flush.
		self deferCallbacks: (EmConstants at: 'EmNclassChangedCallback' asPoolKey)  "$NON-NLS$"
			computedCallData:
				[EmClassChangeCallbackData new
					className: aName;
					applicationName: controllerName;
					changeType:
							(EmConstants at: 'EMCDirectDefinitionChange' asPoolKey)  "$NON-NLS$"
						|	(EmConstants at: 'EMCRemoved' asPoolKey);  "$NON-NLS$"
					yourself]].
	^ removedClass! !

EmSystemConfiguration categoriesFor: #removeClassNamed:from:flush: are: #('EM-Internal')!

!Class privateMethods !

wasRemoved: flush
		"The receiver was just removed from the image so disconnect from its
		 superclass and controller."

	self applications do: [:app |
		app locallyRemove: self].
	self disconnectFromSuper.
	self setClassName: self removedNamePrefix, self symbol.
	self classPool associationsDo: [:assoc |
		assoc value: nil].
	self extraInstanceVariables: nil.
	self class extraInstanceVariables: nil.
	self scrubClassInstanceData.
	"OPTIMIZATION: Explicitly flush cache only once"
	self initializeInactiveMethodDictionary. 
	self class initializeInactiveMethodDictionary.
	flush ifTrue: [self methodDictionary flushCache]! !

Class categoriesFor: #wasRemoved: are: #('EM-Internal')!

================================================================