Kernel-Infrastructure.st 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392
  1. Smalltalk createPackage: 'Kernel-Infrastructure'!
  2. Object subclass: #ConsoleErrorHandler
  3. instanceVariableNames: ''
  4. package: 'Kernel-Infrastructure'!
  5. !ConsoleErrorHandler commentStamp!
  6. I am manage Smalltalk errors, displaying the stack in the console.!
  7. !ConsoleErrorHandler methodsFor: 'error handling'!
  8. handleError: anError
  9. anError context ifNotNil: [ self logErrorContext: anError context ].
  10. self logError: anError
  11. ! !
  12. !ConsoleErrorHandler methodsFor: 'private'!
  13. log: aString
  14. console log: aString
  15. !
  16. logContext: aContext
  17. aContext home ifNotNil: [
  18. self logContext: aContext home ].
  19. self log: aContext asString
  20. !
  21. logError: anError
  22. self log: anError messageText
  23. !
  24. logErrorContext: aContext
  25. aContext ifNotNil: [
  26. aContext home ifNotNil: [
  27. self logContext: aContext home ]]
  28. ! !
  29. ConsoleErrorHandler class instanceVariableNames: 'current'!
  30. !ConsoleErrorHandler class methodsFor: 'initialization'!
  31. initialize
  32. ErrorHandler registerIfNone: self new
  33. ! !
  34. Object subclass: #InterfacingObject
  35. instanceVariableNames: ''
  36. package: 'Kernel-Infrastructure'!
  37. !InterfacingObject commentStamp!
  38. I am superclass of all object that interface with user or environment. `Widget` and a few other classes are subclasses of me. I delegate all of the above APIs to `PlatformInterface`.
  39. ## API
  40. self alert: 'Hey, there is a problem'.
  41. self confirm: 'Affirmative?'.
  42. self prompt: 'Your name:'.
  43. self ajax: #{
  44. 'url' -> '/patch.js'. 'type' -> 'GET'. dataType->'script'
  45. }.!
  46. !InterfacingObject methodsFor: 'actions'!
  47. ajax: anObject
  48. ^ PlatformInterface ajax: anObject
  49. !
  50. alert: aString
  51. ^ PlatformInterface alert: aString
  52. !
  53. confirm: aString
  54. ^ PlatformInterface confirm: aString
  55. !
  56. prompt: aString
  57. ^ PlatformInterface prompt: aString
  58. ! !
  59. InterfacingObject subclass: #Environment
  60. instanceVariableNames: ''
  61. package: 'Kernel-Infrastructure'!
  62. !Environment commentStamp!
  63. I provide an unified entry point to manipulate Amber packages, classes and methods.
  64. Typical use cases include IDEs, remote access and restricting browsing.!
  65. !Environment methodsFor: 'accessing'!
  66. allSelectors
  67. ^ Smalltalk vm allSelectors
  68. !
  69. availableClassNames
  70. ^ Smalltalk classes
  71. collect: [ :each | each name ]
  72. !
  73. availablePackageNames
  74. ^ Smalltalk packages
  75. collect: [ :each | each name ]
  76. !
  77. availableProtocolsFor: aClass
  78. | protocols |
  79. protocols := aClass protocols.
  80. aClass superclass ifNotNil: [ protocols addAll: (self availableProtocolsFor: aClass superclass) ].
  81. ^ protocols asSet asArray sort
  82. !
  83. classBuilder
  84. ^ ClassBuilder new
  85. !
  86. classNamed: aString
  87. ^ (Smalltalk globals at: aString asSymbol)
  88. ifNil: [ self error: 'Invalid class name' ]
  89. !
  90. classes
  91. ^ Smalltalk classes
  92. !
  93. doItReceiver
  94. ^ DoIt new
  95. !
  96. packages
  97. ^ Smalltalk packages
  98. !
  99. systemAnnouncer
  100. ^ (Smalltalk globals at: #SystemAnnouncer) current
  101. ! !
  102. !Environment methodsFor: 'actions'!
  103. commitPackage: aPackage onSuccess: aBlock onError: anotherBlock
  104. aPackage transport
  105. commitOnSuccess: aBlock
  106. onError: anotherBlock
  107. !
  108. copyClass: aClass to: aClassName
  109. (Smalltalk globals at: aClassName)
  110. ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].
  111. ClassBuilder new copyClass: aClass named: aClassName
  112. !
  113. inspect: anObject
  114. Inspector inspect: anObject
  115. !
  116. moveClass: aClass toPackage: aPackageName
  117. | package |
  118. package := Package named: aPackageName.
  119. package ifNil: [ self error: 'Invalid package name' ].
  120. package == aClass package ifTrue: [ ^ self ].
  121. aClass package: package
  122. !
  123. moveMethod: aMethod toClass: aClassName
  124. | destinationClass |
  125. destinationClass := self classNamed: aClassName.
  126. destinationClass == aMethod methodClass ifTrue: [ ^ self ].
  127. aMethod methodClass isMetaclass ifTrue: [
  128. destinationClass := destinationClass class ].
  129. destinationClass
  130. compile: aMethod source
  131. protocol: aMethod protocol.
  132. aMethod methodClass
  133. removeCompiledMethod: aMethod
  134. !
  135. moveMethod: aMethod toProtocol: aProtocol
  136. aMethod protocol: aProtocol
  137. !
  138. removeClass: aClass
  139. Smalltalk removeClass: aClass
  140. !
  141. removeMethod: aMethod
  142. aMethod methodClass removeCompiledMethod: aMethod
  143. !
  144. removeProtocol: aString from: aClass
  145. (aClass methodsInProtocol: aString)
  146. do: [ :each | aClass removeCompiledMethod: each ]
  147. !
  148. renameClass: aClass to: aClassName
  149. (Smalltalk globals at: aClassName)
  150. ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].
  151. ClassBuilder new renameClass: aClass to: aClassName
  152. !
  153. renameProtocol: aString to: anotherString in: aClass
  154. (aClass methodsInProtocol: aString)
  155. do: [ :each | each protocol: anotherString ]
  156. !
  157. setClassCommentOf: aClass to: aString
  158. aClass comment: aString
  159. ! !
  160. !Environment methodsFor: 'compiling'!
  161. addInstVarNamed: aString to: aClass
  162. self classBuilder
  163. addSubclassOf: aClass superclass
  164. named: aClass name
  165. instanceVariableNames: (aClass instanceVariableNames copy add: aString; yourself)
  166. package: aClass package name
  167. !
  168. compileClassComment: aString for: aClass
  169. aClass comment: aString
  170. !
  171. compileClassDefinition: aString
  172. [ self evaluate: aString for: DoIt new ]
  173. on: Error
  174. do: [ :error | self alert: error messageText ]
  175. !
  176. compileMethod: sourceCode for: class protocol: protocol
  177. ^ class
  178. compile: sourceCode
  179. protocol: protocol
  180. ! !
  181. !Environment methodsFor: 'error handling'!
  182. evaluate: aBlock on: anErrorClass do: exceptionBlock
  183. "Evaluate a block and catch exceptions happening on the environment stack"
  184. aBlock tryCatch: [ :exception |
  185. (exception isKindOf: (self classNamed: anErrorClass name))
  186. ifTrue: [ exceptionBlock value: exception ]
  187. ifFalse: [ exception signal ] ]
  188. ! !
  189. !Environment methodsFor: 'evaluating'!
  190. evaluate: aString for: anObject
  191. ^ Evaluator evaluate: aString for: anObject
  192. ! !
  193. !Environment methodsFor: 'services'!
  194. registerErrorHandler: anErrorHandler
  195. ErrorHandler register: anErrorHandler
  196. !
  197. registerFinder: aFinder
  198. Finder register: aFinder
  199. !
  200. registerInspector: anInspector
  201. Inspector register: anInspector
  202. !
  203. registerProgressHandler: aProgressHandler
  204. ProgressHandler register: aProgressHandler
  205. !
  206. registerTranscript: aTranscript
  207. Transcript register: aTranscript
  208. ! !
  209. ProtoObject subclass: #JSObjectProxy
  210. instanceVariableNames: 'jsObject'
  211. package: 'Kernel-Infrastructure'!
  212. !JSObjectProxy commentStamp!
  213. I handle sending messages to JavaScript objects, making JavaScript object accessing from Amber fully transparent.
  214. My instances make intensive use of `#doesNotUnderstand:`.
  215. My instances are automatically created by Amber whenever a message is sent to a JavaScript object.
  216. ## Usage examples
  217. JSObjectProxy objects are instanciated by Amber when a Smalltalk message is sent to a JavaScript object.
  218. window alert: 'hello world'.
  219. window inspect.
  220. (window jQuery: 'body') append: 'hello world'
  221. Amber messages sends are converted to JavaScript function calls or object property access _(in this order)_. If n one of them match, a `MessageNotUnderstood` error will be thrown.
  222. ## Message conversion rules
  223. - `someUser name` becomes `someUser.name`
  224. - `someUser name: 'John'` becomes `someUser name = "John"`
  225. - `console log: 'hello world'` becomes `console.log('hello world')`
  226. - `(window jQuery: 'foo') css: 'background' color: 'red'` becomes `window.jQuery('foo').css('background', 'red')`
  227. __Note:__ For keyword-based messages, only the first keyword is kept: `window foo: 1 bar: 2` is equivalent to `window foo: 1 baz: 2`.!
  228. !JSObjectProxy methodsFor: 'accessing'!
  229. at: aString
  230. <return self['@jsObject'][aString]>
  231. !
  232. at: aString ifAbsent: aBlock
  233. "return the aString property or evaluate aBlock if the property is not defined on the object"
  234. <
  235. var obj = self['@jsObject'];
  236. return aString in obj ? obj[aString] : aBlock._value();
  237. >
  238. !
  239. at: aString ifPresent: aBlock
  240. "return the evaluation of aBlock with the value if the property is defined or return nil"
  241. <
  242. var obj = self['@jsObject'];
  243. return aString in obj ? aBlock._value_(obj[aString]) : nil;
  244. >
  245. !
  246. at: aString ifPresent: aBlock ifAbsent: anotherBlock
  247. "return the evaluation of aBlock with the value if the property is defined
  248. or return value of anotherBlock"
  249. <
  250. var obj = self['@jsObject'];
  251. return aString in obj ? aBlock._value_(obj[aString]) : anotherBlock._value();
  252. >
  253. !
  254. at: aString put: anObject
  255. <return self['@jsObject'][aString] = anObject>
  256. !
  257. jsObject
  258. ^ jsObject
  259. !
  260. jsObject: aJSObject
  261. jsObject := aJSObject
  262. !
  263. lookupProperty: aString
  264. "Looks up a property in JS object.
  265. Answer the property if it is present, or nil if it is not present."
  266. <return aString in self._jsObject() ? aString : nil>
  267. ! !
  268. !JSObjectProxy methodsFor: 'comparing'!
  269. = anObject
  270. anObject class == self class ifFalse: [ ^ false ].
  271. ^ self compareJSObjectWith: anObject jsObject
  272. ! !
  273. !JSObjectProxy methodsFor: 'enumerating'!
  274. asJSON
  275. "Answers the receiver in a stringyfy-friendly fashion"
  276. ^ jsObject
  277. !
  278. keysAndValuesDo: aBlock
  279. <
  280. var o = self['@jsObject'];
  281. for(var i in o) {
  282. aBlock._value_value_(i, o[i]);
  283. }
  284. >
  285. ! !
  286. !JSObjectProxy methodsFor: 'printing'!
  287. printOn: aStream
  288. aStream nextPutAll: self printString
  289. !
  290. printString
  291. <
  292. var js = self['@jsObject'];
  293. return js.toString
  294. ? js.toString()
  295. : Object.prototype.toString.call(js)
  296. >
  297. ! !
  298. !JSObjectProxy methodsFor: 'private'!
  299. compareJSObjectWith: aJSObject
  300. <return self["@jsObject"] === aJSObject>
  301. ! !
  302. !JSObjectProxy methodsFor: 'proxy'!
  303. addObjectVariablesTo: aDictionary
  304. <
  305. for(var i in self['@jsObject']) {
  306. aDictionary._at_put_(i, self['@jsObject'][i]);
  307. }
  308. >
  309. !
  310. doesNotUnderstand: aMessage
  311. ^ (self lookupProperty: aMessage selector asJavaScriptSelector)
  312. ifNil: [ super doesNotUnderstand: aMessage ]
  313. ifNotNil: [ :jsSelector |
  314. self
  315. forwardMessage: jsSelector
  316. withArguments: aMessage arguments ]
  317. !
  318. forwardMessage: aString withArguments: anArray
  319. <
  320. return smalltalk.send(self._jsObject(), aString, anArray);
  321. >
  322. !
  323. inspectOn: anInspector
  324. | variables |
  325. variables := Dictionary new.
  326. variables at: '#self' put: self jsObject.
  327. anInspector setLabel: self printString.
  328. self addObjectVariablesTo: variables.
  329. anInspector setVariables: variables
  330. ! !
  331. !JSObjectProxy class methodsFor: 'instance creation'!
  332. on: aJSObject
  333. ^ self new
  334. jsObject: aJSObject;
  335. yourself
  336. ! !
  337. Object subclass: #NullProgressHandler
  338. instanceVariableNames: ''
  339. package: 'Kernel-Infrastructure'!
  340. !NullProgressHandler commentStamp!
  341. I am the default progress handler. I do not display any progress, and simply iterate over the collection.!
  342. !NullProgressHandler methodsFor: 'progress handling'!
  343. do: aBlock on: aCollection displaying: aString
  344. aCollection do: aBlock
  345. ! !
  346. NullProgressHandler class instanceVariableNames: 'current'!
  347. !NullProgressHandler class methodsFor: 'initialization'!
  348. initialize
  349. ProgressHandler registerIfNone: self new
  350. ! !
  351. Object subclass: #Organizer
  352. instanceVariableNames: ''
  353. package: 'Kernel-Infrastructure'!
  354. !Organizer commentStamp!
  355. I represent categorization information.
  356. ## API
  357. Use `#addElement:` and `#removeElement:` to manipulate instances.!
  358. !Organizer methodsFor: 'accessing'!
  359. addElement: anObject
  360. <self.elements.addElement(anObject)>
  361. !
  362. elements
  363. ^ (self basicAt: 'elements') copy
  364. !
  365. removeElement: anObject
  366. <self.elements.removeElement(anObject)>
  367. ! !
  368. Organizer subclass: #ClassOrganizer
  369. instanceVariableNames: ''
  370. package: 'Kernel-Infrastructure'!
  371. !ClassOrganizer commentStamp!
  372. I am an organizer specific to classes. I hold method categorization information for classes.!
  373. !ClassOrganizer methodsFor: 'accessing'!
  374. addElement: aString
  375. super addElement: aString.
  376. SystemAnnouncer current announce: (ProtocolAdded new
  377. protocol: aString;
  378. theClass: self theClass;
  379. yourself)
  380. !
  381. removeElement: aString
  382. super removeElement: aString.
  383. SystemAnnouncer current announce: (ProtocolRemoved new
  384. protocol: aString;
  385. theClass: self theClass;
  386. yourself)
  387. !
  388. theClass
  389. < return self.theClass >
  390. ! !
  391. Organizer subclass: #PackageOrganizer
  392. instanceVariableNames: ''
  393. package: 'Kernel-Infrastructure'!
  394. !PackageOrganizer commentStamp!
  395. I am an organizer specific to packages. I hold classes categorization information.!
  396. Object subclass: #Package
  397. instanceVariableNames: 'transport dirty'
  398. package: 'Kernel-Infrastructure'!
  399. !Package commentStamp!
  400. I am similar to a "class category" typically found in other Smalltalks like Pharo or Squeak. Amber does not have class categories anymore, it had in the beginning but now each class in the system knows which package it belongs to.
  401. Each package has a name and can be queried for its classes, but it will then resort to a reverse scan of all classes to find them.
  402. ## API
  403. Packages are manipulated through "Smalltalk current", like for example finding one based on a name or with `Package class >> #name` directly:
  404. Smalltalk current packageAt: 'Kernel'
  405. Package named: 'Kernel'
  406. A package differs slightly from a Monticello package which can span multiple class categories using a naming convention based on hyphenation. But just as in Monticello a package supports "class extensions" so a package can define behaviors in foreign classes using a naming convention for method categories where the category starts with an asterisk and then the name of the owning package follows.
  407. You can fetch a package from the server:
  408. Package load: 'Additional-Examples'!
  409. !Package methodsFor: 'accessing'!
  410. beClean
  411. dirty := false.
  412. SystemAnnouncer current announce: (PackageClean new
  413. package: self;
  414. yourself)
  415. !
  416. beDirty
  417. dirty := true.
  418. SystemAnnouncer current announce: (PackageClean new
  419. package: self;
  420. yourself)
  421. !
  422. classTemplate
  423. ^ String streamContents: [ :stream |
  424. stream
  425. nextPutAll: 'Object';
  426. nextPutAll: ' subclass: #NameOfSubclass';
  427. nextPutAll: String lf, String tab;
  428. nextPutAll: 'instanceVariableNames: '''''.
  429. stream
  430. nextPutAll: '''', String lf, String tab;
  431. nextPutAll: 'package: ''';
  432. nextPutAll: self name;
  433. nextPutAll: '''' ]
  434. !
  435. definition
  436. ^ String streamContents: [ :stream |
  437. stream
  438. nextPutAll: self class name;
  439. nextPutAll: String lf, String tab;
  440. nextPutAll: ' named: ';
  441. nextPutAll: '''', self name, '''';
  442. nextPutAll: String lf, String tab;
  443. nextPutAll: ' transport: (';
  444. nextPutAll: self transport definition, ')' ]
  445. !
  446. name
  447. <return self.pkgName>
  448. !
  449. name: aString
  450. self basicName: aString.
  451. self beDirty
  452. !
  453. organization
  454. ^ self basicAt: 'organization'
  455. !
  456. transport
  457. ^ transport ifNil: [
  458. transport := (PackageTransport fromJson: self basicTransport)
  459. package: self;
  460. yourself ]
  461. !
  462. transport: aPackageTransport
  463. transport := aPackageTransport.
  464. aPackageTransport package: self
  465. ! !
  466. !Package methodsFor: 'classes'!
  467. classes
  468. ^ self organization elements
  469. !
  470. setupClasses
  471. self classes
  472. do: [ :each | ClassBuilder new setupClass: each ];
  473. do: [ :each | each initialize ]
  474. !
  475. sortedClasses
  476. "Answer all classes in the receiver, sorted by superclass/subclasses and by class name for common subclasses (Issue #143)."
  477. ^ self class sortedClasses: self classes
  478. ! !
  479. !Package methodsFor: 'dependencies'!
  480. loadDependencies
  481. "Returns list of packages that need to be loaded
  482. before loading this package."
  483. | classes packages |
  484. classes := self loadDependencyClasses.
  485. ^ (classes collect: [ :each | each package ]) asSet
  486. remove: self ifAbsent: [];
  487. yourself
  488. !
  489. loadDependencyClasses
  490. "Returns classes needed at the time of loading a package.
  491. These are all that are used to subclass
  492. and to define an extension method"
  493. | starCategoryName |
  494. starCategoryName := '*', self name.
  495. ^ (self classes collect: [ :each | each superclass ]) asSet
  496. remove: nil ifAbsent: [];
  497. addAll: (Smalltalk classes select: [ :each | each protocols, each class protocols includes: starCategoryName ]);
  498. yourself
  499. ! !
  500. !Package methodsFor: 'printing'!
  501. printOn: aStream
  502. super printOn: aStream.
  503. aStream
  504. nextPutAll: ' (';
  505. nextPutAll: self name;
  506. nextPutAll: ')'
  507. ! !
  508. !Package methodsFor: 'private'!
  509. basicName: aString
  510. <self.pkgName = aString>
  511. !
  512. basicTransport
  513. "Answer the transport literal JavaScript object as setup in the JavaScript file, if any"
  514. <return self.transport>
  515. ! !
  516. !Package methodsFor: 'testing'!
  517. isDirty
  518. ^ dirty ifNil: [ false ]
  519. !
  520. isPackage
  521. ^ true
  522. ! !
  523. Package class instanceVariableNames: 'defaultCommitPathJs defaultCommitPathSt'!
  524. !Package class methodsFor: 'accessing'!
  525. named: aPackageName
  526. ^ Smalltalk
  527. packageAt: aPackageName
  528. ifAbsent: [
  529. Smalltalk createPackage: aPackageName ]
  530. !
  531. named: aPackageName ifAbsent: aBlock
  532. ^ Smalltalk packageAt: aPackageName ifAbsent: aBlock
  533. !
  534. named: aPackageName transport: aTransport
  535. | package |
  536. package := self named: aPackageName.
  537. package transport: aTransport.
  538. ^ package
  539. ! !
  540. !Package class methodsFor: 'sorting'!
  541. sortedClasses: classes
  542. "Answer classes, sorted by superclass/subclasses and by class name for common subclasses (Issue #143)"
  543. | children others nodes expandedClasses |
  544. children := #().
  545. others := #().
  546. classes do: [ :each |
  547. (classes includes: each superclass)
  548. ifFalse: [ children add: each ]
  549. ifTrue: [ others add: each ]].
  550. nodes := children collect: [ :each |
  551. ClassSorterNode on: each classes: others level: 0 ].
  552. nodes := nodes sorted: [ :a :b | a theClass name <= b theClass name ].
  553. expandedClasses := Array new.
  554. nodes do: [ :aNode |
  555. aNode traverseClassesWith: expandedClasses ].
  556. ^ expandedClasses
  557. ! !
  558. Object subclass: #PackageStateObserver
  559. instanceVariableNames: ''
  560. package: 'Kernel-Infrastructure'!
  561. !PackageStateObserver commentStamp!
  562. My current instance listens for any changes in the system that might affect the state of a package (being dirty).!
  563. !PackageStateObserver methodsFor: 'accessing'!
  564. announcer
  565. ^ SystemAnnouncer current
  566. ! !
  567. !PackageStateObserver methodsFor: 'actions'!
  568. observeSystem
  569. self announcer
  570. on: PackageAdded
  571. send: #onPackageAdded:
  572. to: self;
  573. on: ClassAnnouncement
  574. send: #onClassModification:
  575. to: self;
  576. on: MethodAnnouncement
  577. send: #onMethodModification:
  578. to: self;
  579. on: ProtocolAnnouncement
  580. send: #onProtocolModification:
  581. to: self
  582. ! !
  583. !PackageStateObserver methodsFor: 'reactions'!
  584. onClassModification: anAnnouncement
  585. anAnnouncement theClass ifNotNil: [ :theClass |
  586. theClass package beDirty ]
  587. !
  588. onMethodModification: anAnnouncement
  589. anAnnouncement method package ifNotNil: [ :package | package beDirty ]
  590. !
  591. onPackageAdded: anAnnouncement
  592. anAnnouncement package beDirty
  593. !
  594. onProtocolModification: anAnnouncement
  595. anAnnouncement theClass package beDirty
  596. ! !
  597. PackageStateObserver class instanceVariableNames: 'current'!
  598. !PackageStateObserver class methodsFor: 'accessing'!
  599. current
  600. ^ current ifNil: [ current := self new ]
  601. ! !
  602. !PackageStateObserver class methodsFor: 'initialization'!
  603. initialize
  604. self current observeSystem
  605. ! !
  606. Object subclass: #PlatformInterface
  607. instanceVariableNames: ''
  608. package: 'Kernel-Infrastructure'!
  609. !PlatformInterface commentStamp!
  610. I am single entry point to UI and environment interface.
  611. My `initialize` tries several options (for now, browser environment only) to set myself up.
  612. ## API
  613. PlatformInterface alert: 'Hey, there is a problem'.
  614. PlatformInterface confirm: 'Affirmative?'.
  615. PlatformInterface prompt: 'Your name:'.
  616. PlatformInterface ajax: #{
  617. 'url' -> '/patch.js'. 'type' -> 'GET'. dataType->'script'
  618. }.!
  619. PlatformInterface class instanceVariableNames: 'worker'!
  620. !PlatformInterface class methodsFor: 'accessing'!
  621. globals
  622. <return (new Function('return this'))();>
  623. !
  624. setWorker: anObject
  625. worker := anObject
  626. ! !
  627. !PlatformInterface class methodsFor: 'actions'!
  628. ajax: anObject
  629. ^ worker
  630. ifNotNil: [ worker ajax: anObject ]
  631. ifNil: [ self error: 'ajax: not available' ]
  632. !
  633. alert: aString
  634. ^ worker
  635. ifNotNil: [ worker alert: aString ]
  636. ifNil: [ self error: 'alert: not available' ]
  637. !
  638. confirm: aString
  639. ^ worker
  640. ifNotNil: [ worker confirm: aString ]
  641. ifNil: [ self error: 'confirm: not available' ]
  642. !
  643. existsGlobal: aString
  644. ^ PlatformInterface globals
  645. at: aString
  646. ifPresent: [ true ]
  647. ifAbsent: [ false ]
  648. !
  649. prompt: aString
  650. ^ worker
  651. ifNotNil: [ worker prompt: aString ]
  652. ifNil: [ self error: 'prompt: not available' ]
  653. ! !
  654. !PlatformInterface class methodsFor: 'initialization'!
  655. initialize
  656. | candidate |
  657. super initialize.
  658. BrowserInterface ifNotNil: [
  659. candidate := BrowserInterface new.
  660. candidate isAvailable ifTrue: [ self setWorker: candidate. ^ self ]
  661. ]
  662. ! !
  663. Object subclass: #Service
  664. instanceVariableNames: ''
  665. package: 'Kernel-Infrastructure'!
  666. !Service commentStamp!
  667. I implement the basic behavior for class registration to a service.
  668. See the `Transcript` class for a concrete service.
  669. ## API
  670. Use class-side methods `#register:` and `#registerIfNone:` to register classes to a specific service.!
  671. Service class instanceVariableNames: 'current'!
  672. !Service class methodsFor: 'accessing'!
  673. current
  674. ^ current
  675. ! !
  676. !Service class methodsFor: 'instance creation'!
  677. new
  678. self shouldNotImplement
  679. ! !
  680. !Service class methodsFor: 'registration'!
  681. register: anObject
  682. current := anObject
  683. !
  684. registerIfNone: anObject
  685. self current ifNil: [ self register: anObject ]
  686. ! !
  687. Service subclass: #ErrorHandler
  688. instanceVariableNames: ''
  689. package: 'Kernel-Infrastructure'!
  690. !ErrorHandler commentStamp!
  691. I am the service used to handle Smalltalk errors.
  692. See `boot.js` `handleError()` function.
  693. Registered service instances must implement `#handleError:` to perform an action on the thrown exception.!
  694. !ErrorHandler class methodsFor: 'error handling'!
  695. handleError: anError
  696. self handleUnhandledError: anError
  697. !
  698. handleUnhandledError: anError
  699. anError wasHandled ifTrue: [ ^ self ].
  700. ^ self current handleError: anError
  701. ! !
  702. Service subclass: #Finder
  703. instanceVariableNames: ''
  704. package: 'Kernel-Infrastructure'!
  705. !Finder commentStamp!
  706. I am the service responsible for finding classes/methods.
  707. __There is no default finder.__
  708. ## API
  709. Use `#browse` on an object to find it.!
  710. !Finder class methodsFor: 'finding'!
  711. findClass: aClass
  712. ^ self current findClass: aClass
  713. !
  714. findMethod: aCompiledMethod
  715. ^ self current findMethod: aCompiledMethod
  716. !
  717. findString: aString
  718. ^ self current findString: aString
  719. ! !
  720. Service subclass: #Inspector
  721. instanceVariableNames: ''
  722. package: 'Kernel-Infrastructure'!
  723. !Inspector commentStamp!
  724. I am the service responsible for inspecting objects.
  725. The default inspector object is the transcript.!
  726. !Inspector class methodsFor: 'inspecting'!
  727. inspect: anObject
  728. ^ self current inspect: anObject
  729. ! !
  730. Service subclass: #ProgressHandler
  731. instanceVariableNames: ''
  732. package: 'Kernel-Infrastructure'!
  733. !ProgressHandler commentStamp!
  734. I am used to manage progress in collection iterations, see `SequenceableCollection >> #do:displayingProgress:`.
  735. Registered instances must implement `#do:on:displaying:`.
  736. The default behavior is to simply iterate over the collection, using `NullProgressHandler`.!
  737. !ProgressHandler class methodsFor: 'progress handling'!
  738. do: aBlock on: aCollection displaying: aString
  739. self current do: aBlock on: aCollection displaying: aString
  740. ! !
  741. Service subclass: #Transcript
  742. instanceVariableNames: ''
  743. package: 'Kernel-Infrastructure'!
  744. !Transcript commentStamp!
  745. I am a facade for Transcript actions.
  746. I delegate actions to the currently registered transcript.
  747. ## API
  748. Transcript
  749. show: 'hello world';
  750. cr;
  751. show: anObject.!
  752. !Transcript class methodsFor: 'instance creation'!
  753. open
  754. self current open
  755. ! !
  756. !Transcript class methodsFor: 'printing'!
  757. clear
  758. self current clear
  759. !
  760. cr
  761. self current show: String cr
  762. !
  763. inspect: anObject
  764. self show: anObject
  765. !
  766. show: anObject
  767. self current show: anObject
  768. ! !
  769. Object subclass: #Setting
  770. instanceVariableNames: 'key value defaultValue'
  771. package: 'Kernel-Infrastructure'!
  772. !Setting commentStamp!
  773. I represent a setting accessible via `Smalltalk settings`.
  774. ## API
  775. A `Setting` value can be read using `value` and set using `value:`.
  776. Settings are accessed with `'key' asSetting` or `'key' asSettingIfAbsent: 'defaultValue'`.!
  777. !Setting methodsFor: 'accessing'!
  778. defaultValue
  779. ^ defaultValue
  780. !
  781. defaultValue: anObject
  782. defaultValue := anObject
  783. !
  784. key
  785. ^ key
  786. !
  787. key: anObject
  788. key := anObject
  789. !
  790. value
  791. ^ Smalltalk settings at: self key ifAbsent: [ self defaultValue ]
  792. !
  793. value: aString
  794. ^ Smalltalk settings at: self key put: aString
  795. ! !
  796. !Setting class methodsFor: 'instance creation'!
  797. at: aString ifAbsent: anotherString
  798. ^ super new
  799. key: aString;
  800. defaultValue: anotherString;
  801. yourself
  802. !
  803. new
  804. self shouldNotImplement
  805. ! !
  806. Object subclass: #SmalltalkImage
  807. instanceVariableNames: ''
  808. package: 'Kernel-Infrastructure'!
  809. !SmalltalkImage commentStamp!
  810. I represent the Smalltalk system, wrapping
  811. operations of variable `smalltalk` declared in `support/boot.js`.
  812. ## API
  813. I have only one instance, accessed with global variable `Smalltalk`.
  814. The `smalltalk` object holds all class and packages defined in the system.
  815. ## Classes
  816. Classes can be accessed using the following methods:
  817. - `#classes` answers the full list of Smalltalk classes in the system
  818. - `#at:` answers a specific class or `nil`
  819. ## Packages
  820. Packages can be accessed using the following methods:
  821. - `#packages` answers the full list of packages
  822. - `#packageAt:` answers a specific package or `nil`
  823. ## Parsing
  824. The `#parse:` method is used to parse Amber source code.
  825. It requires the `Compiler` package and the `support/parser.js` parser file in order to work.!
  826. !SmalltalkImage methodsFor: 'accessing'!
  827. at: aString
  828. self deprecatedAPI.
  829. ^ self globals at: aString
  830. !
  831. at: aKey ifAbsent: aBlock
  832. ^ (self includesKey: aKey)
  833. ifTrue: [ self at: aKey ]
  834. ifFalse: [ aBlock value ]
  835. !
  836. at: aString put: anObject
  837. self deprecatedAPI.
  838. ^ self globals at: aString put: anObject
  839. !
  840. current
  841. "Backward compatibility for Smalltalk current ..."
  842. self deprecatedAPI.
  843. ^ self
  844. !
  845. globals
  846. "Future compatibility to be able to use Smalltalk globals at: ..."
  847. <return globals>
  848. !
  849. includesKey: aKey
  850. <return smalltalk.hasOwnProperty(aKey)>
  851. !
  852. parse: aString
  853. | result |
  854. [ result := self basicParse: aString ]
  855. tryCatch: [ :ex | (self parseError: ex parsing: aString) signal ].
  856. ^ result
  857. source: aString;
  858. yourself
  859. !
  860. pseudoVariableNames
  861. ^ #('self' 'super' 'nil' 'true' 'false' 'thisContext')
  862. !
  863. readJSObject: anObject
  864. <return smalltalk.readJSObject(anObject)>
  865. !
  866. reservedWords
  867. "JavaScript reserved words"
  868. <return smalltalk.reservedWords>
  869. !
  870. settings
  871. ^ SmalltalkSettings
  872. !
  873. version
  874. "Answer the version string of Amber"
  875. ^ '0.13.0-pre'
  876. !
  877. vm
  878. "Future compatibility to be able to use Smalltalk vm ..."
  879. <return smalltalk>
  880. ! !
  881. !SmalltalkImage methodsFor: 'accessing amd'!
  882. amdRequire
  883. ^ self vm at: 'amdRequire'
  884. !
  885. defaultAmdNamespace
  886. ^ 'transport.defaultAmdNamespace' settingValue
  887. !
  888. defaultAmdNamespace: aString
  889. 'transport.defaultAmdNamespace' settingValue: aString
  890. ! !
  891. !SmalltalkImage methodsFor: 'classes'!
  892. classes
  893. <return smalltalk.classes()>
  894. !
  895. removeClass: aClass
  896. aClass isMetaclass ifTrue: [ self error: aClass asString, ' is a Metaclass and cannot be removed!!' ].
  897. self deleteClass: aClass.
  898. SystemAnnouncer current
  899. announce: (ClassRemoved new
  900. theClass: aClass;
  901. yourself)
  902. ! !
  903. !SmalltalkImage methodsFor: 'error handling'!
  904. asSmalltalkException: anObject
  905. "A JavaScript exception may be thrown.
  906. We then need to convert it back to a Smalltalk object"
  907. ^ ((self isSmalltalkObject: anObject) and: [ anObject isKindOf: Error ])
  908. ifTrue: [ anObject ]
  909. ifFalse: [ JavaScriptException on: anObject ]
  910. !
  911. parseError: anException parsing: aString
  912. ^ ParseError new messageText: 'Parse error on line ', (anException basicAt: 'line') ,' column ' , (anException basicAt: 'column') ,' : Unexpected character ', (anException basicAt: 'found')
  913. ! !
  914. !SmalltalkImage methodsFor: 'globals'!
  915. addGlobalJsVariable: aString
  916. self globalJsVariables add: aString
  917. !
  918. deleteGlobalJsVariable: aString
  919. self globalJsVariables remove: aString ifAbsent:[]
  920. !
  921. globalJsVariables
  922. "Array of global JavaScript variables"
  923. <return smalltalk.globalJsVariables>
  924. ! !
  925. !SmalltalkImage methodsFor: 'packages'!
  926. createPackage: packageName
  927. | package announcement |
  928. package := self basicCreatePackage: packageName.
  929. announcement := PackageAdded new
  930. package: package;
  931. yourself.
  932. SystemAnnouncer current announce: announcement.
  933. ^ package
  934. !
  935. packageAt: packageName
  936. <return smalltalk.packages[packageName]>
  937. !
  938. packageAt: packageName ifAbsent: aBlock
  939. ^ (self packageAt: packageName) ifNil: aBlock
  940. !
  941. packages
  942. "Return all Package instances in the system."
  943. <
  944. return Object.keys(smalltalk.packages).map(function(k) {
  945. return smalltalk.packages[k];
  946. })
  947. >
  948. !
  949. removePackage: packageName
  950. "Removes a package and all its classes."
  951. | pkg |
  952. pkg := self packageAt: packageName ifAbsent: [ self error: 'Missing package: ', packageName ].
  953. pkg classes do: [ :each |
  954. self removeClass: each ].
  955. self deletePackage: packageName
  956. !
  957. renamePackage: packageName to: newName
  958. "Rename a package."
  959. | pkg |
  960. pkg := self packageAt: packageName ifAbsent: [ self error: 'Missing package: ', packageName ].
  961. (self packageAt: newName) ifNotNil: [ self error: 'Already exists a package called: ', newName ].
  962. (self at: 'packages') at: newName put: pkg.
  963. pkg name: newName.
  964. self deletePackage: packageName.
  965. ! !
  966. !SmalltalkImage methodsFor: 'private'!
  967. basicCreatePackage: packageName
  968. "Create and bind a new bare package with given name and return it."
  969. <return smalltalk.addPackage(packageName)>
  970. !
  971. basicParse: aString
  972. ^ SmalltalkParser parse: aString
  973. !
  974. createPackage: packageName properties: aDict
  975. "Needed to import .st files: they begin with this call."
  976. self deprecatedAPI.
  977. aDict isEmpty ifFalse: [ self error: 'createPackage:properties: called with nonempty properties' ].
  978. ^ self createPackage: packageName
  979. !
  980. deleteClass: aClass
  981. "Deletes a class by deleting its binding only. Use #removeClass instead"
  982. <smalltalk.removeClass(aClass)>
  983. !
  984. deletePackage: packageName
  985. "Deletes a package by deleting its binding, but does not check if it contains classes etc.
  986. To remove a package, use #removePackage instead."
  987. <delete smalltalk.packages[packageName]>
  988. ! !
  989. !SmalltalkImage methodsFor: 'testing'!
  990. isSmalltalkObject: anObject
  991. "Consider anObject a Smalltalk object if it has a 'klass' property.
  992. Note that this may be unaccurate"
  993. <return typeof anObject.klass !!== 'undefined'>
  994. ! !
  995. SmalltalkImage class instanceVariableNames: 'current'!
  996. !SmalltalkImage class methodsFor: 'initialization'!
  997. initialize
  998. globals at: 'Smalltalk' put: self current
  999. ! !
  1000. !SmalltalkImage class methodsFor: 'instance creation'!
  1001. current
  1002. ^ current ifNil: [ current := super new ] ifNotNil: [ self deprecatedAPI. current ]
  1003. !
  1004. new
  1005. self shouldNotImplement
  1006. ! !
  1007. !SequenceableCollection methodsFor: '*Kernel-Infrastructure'!
  1008. do: aBlock displayingProgress: aString
  1009. ProgressHandler
  1010. do: aBlock
  1011. on: self
  1012. displaying: aString
  1013. ! !
  1014. !String methodsFor: '*Kernel-Infrastructure'!
  1015. asJavaScriptSelector
  1016. "Return first keyword of the selector, without trailing colon."
  1017. ^ self replace: '^([a-zA-Z0-9]*).*$' with: '$1'
  1018. !
  1019. asSetting
  1020. ^ Setting at: self ifAbsent: nil
  1021. !
  1022. asSettingIfAbsent: aString
  1023. ^ Setting at: self ifAbsent: aString
  1024. !
  1025. settingValue
  1026. ^ self asSetting value
  1027. !
  1028. settingValue: aString
  1029. ^ self asSetting value: aString
  1030. !
  1031. settingValueIfAbsent: aString
  1032. ^ (self asSettingIfAbsent: aString) value
  1033. ! !