Platform-Services.st 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. Smalltalk createPackage: 'Platform-Services'!
  2. Object subclass: #ConsoleErrorHandler
  3. instanceVariableNames: ''
  4. package: 'Platform-Services'!
  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: #ConsoleTranscript
  35. instanceVariableNames: 'textarea'
  36. package: 'Platform-Services'!
  37. !ConsoleTranscript commentStamp!
  38. I am a specific transcript emitting to the JavaScript console.
  39. If no other transcript is registered, I am the default.!
  40. !ConsoleTranscript methodsFor: 'actions'!
  41. open
  42. ! !
  43. !ConsoleTranscript methodsFor: 'printing'!
  44. clear
  45. "no op"
  46. !
  47. cr
  48. "no op"
  49. !
  50. show: anObject
  51. "Smalltalk objects should have no trouble displaying themselves on the Transcript; Javascript objects don't know how, so must be wrapped in a JSObectProxy."
  52. <console.log(String($recv(anObject)._asString()))>
  53. ! !
  54. !ConsoleTranscript class methodsFor: 'initialization'!
  55. initialize
  56. Transcript registerIfNone: self new
  57. ! !
  58. Object subclass: #Environment
  59. instanceVariableNames: ''
  60. package: 'Platform-Services'!
  61. !Environment commentStamp!
  62. I provide an unified entry point to manipulate Amber packages, classes and methods.
  63. Typical use cases include IDEs, remote access and restricting browsing.!
  64. !Environment methodsFor: 'accessing'!
  65. allSelectors
  66. ^ Smalltalk core allSelectors
  67. !
  68. availableClassNames
  69. ^ Smalltalk classes
  70. collect: [ :each | each name ]
  71. !
  72. availablePackageNames
  73. ^ Smalltalk packages
  74. collect: [ :each | each name ]
  75. !
  76. availableProtocolsFor: aClass
  77. | protocols |
  78. protocols := aClass protocols.
  79. aClass superclass ifNotNil: [ protocols addAll: (self availableProtocolsFor: aClass superclass) ].
  80. ^ protocols asSet asArray sort
  81. !
  82. classBuilder
  83. ^ ClassBuilder new
  84. !
  85. classNamed: aString
  86. ^ (Smalltalk globals at: aString asSymbol)
  87. ifNil: [ self error: 'Invalid class name' ]
  88. !
  89. classes
  90. ^ Smalltalk classes
  91. !
  92. doItReceiver
  93. ^ DoIt new
  94. !
  95. packages
  96. ^ Smalltalk packages
  97. !
  98. systemAnnouncer
  99. ^ (Smalltalk globals at: #SystemAnnouncer) current
  100. ! !
  101. !Environment methodsFor: 'actions'!
  102. commitPackage: aPackage onSuccess: aBlock onError: anotherBlock
  103. aPackage transport
  104. commitOnSuccess: aBlock
  105. onError: anotherBlock
  106. !
  107. copyClass: aClass to: aClassName
  108. (Smalltalk globals at: aClassName)
  109. ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].
  110. ClassBuilder new copyClass: aClass named: aClassName
  111. !
  112. inspect: anObject
  113. Inspector inspect: anObject
  114. !
  115. moveClass: aClass toPackage: aPackageName
  116. | package |
  117. package := Package named: aPackageName.
  118. package ifNil: [ self error: 'Invalid package name' ].
  119. package == aClass package ifTrue: [ ^ self ].
  120. aClass package: package
  121. !
  122. moveMethod: aMethod toClass: aClassName
  123. | destinationClass |
  124. destinationClass := self classNamed: aClassName.
  125. destinationClass == aMethod methodClass ifTrue: [ ^ self ].
  126. aMethod methodClass isMetaclass ifTrue: [
  127. destinationClass := destinationClass class ].
  128. destinationClass
  129. compile: aMethod source
  130. protocol: aMethod protocol.
  131. aMethod methodClass
  132. removeCompiledMethod: aMethod
  133. !
  134. moveMethod: aMethod toProtocol: aProtocol
  135. aMethod protocol: aProtocol
  136. !
  137. removeClass: aClass
  138. Smalltalk removeClass: aClass
  139. !
  140. removeMethod: aMethod
  141. aMethod methodClass removeCompiledMethod: aMethod
  142. !
  143. removeProtocol: aString from: aClass
  144. (aClass methodsInProtocol: aString)
  145. do: [ :each | aClass removeCompiledMethod: each ]
  146. !
  147. renameClass: aClass to: aClassName
  148. (Smalltalk globals at: aClassName)
  149. ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].
  150. ClassBuilder new renameClass: aClass to: aClassName
  151. !
  152. renamePackage: aPackageName to: aNewPackageName
  153. (Smalltalk globals at: aNewPackageName)
  154. ifNotNil: [ self error: 'A package named ', aNewPackageName, ' already exists' ].
  155. Smalltalk renamePackage: aPackageName to: aNewPackageName
  156. !
  157. renameProtocol: aString to: anotherString in: aClass
  158. (aClass methodsInProtocol: aString)
  159. do: [ :each | each protocol: anotherString ]
  160. !
  161. setClassCommentOf: aClass to: aString
  162. aClass comment: aString
  163. ! !
  164. !Environment methodsFor: 'compiling'!
  165. addInstVarNamed: aString to: aClass
  166. self classBuilder
  167. addSubclassOf: aClass superclass
  168. named: aClass name
  169. instanceVariableNames: (aClass instanceVariableNames copy add: aString; yourself)
  170. package: aClass package name
  171. !
  172. compileClassComment: aString for: aClass
  173. aClass comment: aString
  174. !
  175. compileClassDefinition: aString
  176. [ self evaluate: aString for: DoIt new ]
  177. on: Error
  178. do: [ :error | Terminal alert: error messageText ]
  179. !
  180. compileMethod: sourceCode for: class protocol: protocol
  181. ^ class
  182. compile: sourceCode
  183. protocol: protocol
  184. ! !
  185. !Environment methodsFor: 'error handling'!
  186. evaluate: aBlock on: anErrorClass do: exceptionBlock
  187. "Evaluate a block and catch exceptions happening on the environment stack"
  188. aBlock tryCatch: [ :exception |
  189. (exception isKindOf: (self classNamed: anErrorClass name))
  190. ifTrue: [ exceptionBlock value: exception ]
  191. ifFalse: [ exception resignal ] ]
  192. ! !
  193. !Environment methodsFor: 'evaluating'!
  194. evaluate: aString for: anObject
  195. ^ Evaluator evaluate: aString for: anObject
  196. ! !
  197. !Environment methodsFor: 'services'!
  198. registerErrorHandler: anErrorHandler
  199. ErrorHandler register: anErrorHandler
  200. !
  201. registerFinder: aFinder
  202. Finder register: aFinder
  203. !
  204. registerInspector: anInspector
  205. Inspector register: anInspector
  206. !
  207. registerProgressHandler: aProgressHandler
  208. ProgressHandler register: aProgressHandler
  209. !
  210. registerTranscript: aTranscript
  211. Transcript register: aTranscript
  212. ! !
  213. Object subclass: #NullProgressHandler
  214. instanceVariableNames: ''
  215. package: 'Platform-Services'!
  216. !NullProgressHandler commentStamp!
  217. I am the default progress handler. I do not display any progress, and simply iterate over the collection.!
  218. !NullProgressHandler methodsFor: 'progress handling'!
  219. do: aBlock on: aCollection displaying: aString
  220. aCollection do: aBlock
  221. ! !
  222. NullProgressHandler class instanceVariableNames: 'current'!
  223. !NullProgressHandler class methodsFor: 'initialization'!
  224. initialize
  225. ProgressHandler registerIfNone: self new
  226. ! !
  227. Object subclass: #PlatformInterface
  228. instanceVariableNames: ''
  229. package: 'Platform-Services'!
  230. !PlatformInterface commentStamp!
  231. Deprecated. Use `Platform` or `Terminal`.!
  232. !PlatformInterface class methodsFor: 'accessing'!
  233. globals
  234. self deprecatedAPI: 'Use Platform globals'.
  235. ^ Platform globals
  236. ! !
  237. !PlatformInterface class methodsFor: 'actions'!
  238. ajax: anObject
  239. self deprecatedAPI: 'Use Platform newXhr or dedicated library.'.
  240. ^ JQuery
  241. ifNotNil: [ JQuery current ajax: anObject ]
  242. ifNil: [ self error: 'JQuery wrapper not loaded, cannot do AJAX.' ]
  243. !
  244. alert: aString
  245. self deprecatedAPI: 'Use Terminal alert:'.
  246. ^ Terminal alert: aString
  247. !
  248. confirm: aString
  249. self deprecatedAPI: 'Use Terminal confirm:'.
  250. ^ Terminal confirm: aString
  251. !
  252. existsGlobal: aString
  253. self deprecatedAPI: 'Use Smalltalk existsJsGlobal:'.
  254. ^ PlatformInterface globals
  255. at: aString
  256. ifPresent: [ true ]
  257. ifAbsent: [ false ]
  258. !
  259. newXhr
  260. self deprecatedAPI: 'Use Platform newXhr'.
  261. ^ Platform newXhr
  262. !
  263. prompt: aString
  264. self deprecatedAPI: 'Use Terminal prompt:'.
  265. ^ Terminal prompt: aString
  266. !
  267. prompt: aString default: defaultString
  268. self deprecatedAPI: 'Use Terminal prompt:default:'.
  269. ^ Terminal prompt: aString default: defaultString
  270. ! !
  271. Object subclass: #Service
  272. instanceVariableNames: ''
  273. package: 'Platform-Services'!
  274. !Service commentStamp!
  275. I implement the basic behavior for class registration to a service.
  276. See the `Transcript` class for a concrete service.
  277. ## API
  278. Use class-side methods `#register:` and `#registerIfNone:` to register classes to a specific service.!
  279. Service class instanceVariableNames: 'current'!
  280. !Service class methodsFor: 'accessing'!
  281. current
  282. ^ current
  283. ! !
  284. !Service class methodsFor: 'instance creation'!
  285. new
  286. self shouldNotImplement
  287. ! !
  288. !Service class methodsFor: 'registration'!
  289. register: anObject
  290. current := anObject
  291. !
  292. registerIfNone: anObject
  293. self current ifNil: [ self register: anObject ]
  294. ! !
  295. Service subclass: #ErrorHandler
  296. instanceVariableNames: ''
  297. package: 'Platform-Services'!
  298. !ErrorHandler commentStamp!
  299. I am the service used to handle Smalltalk errors.
  300. See `boot.js` `handleError()` function.
  301. Registered service instances must implement `#handleError:` to perform an action on the thrown exception.!
  302. !ErrorHandler class methodsFor: 'error handling'!
  303. handleError: anError
  304. self handleUnhandledError: anError
  305. !
  306. handleUnhandledError: anError
  307. anError wasHandled ifTrue: [ ^ self ].
  308. ^ self current handleError: anError
  309. ! !
  310. Service subclass: #Finder
  311. instanceVariableNames: ''
  312. package: 'Platform-Services'!
  313. !Finder commentStamp!
  314. I am the service responsible for finding classes/methods.
  315. __There is no default finder.__
  316. ## API
  317. Use `#browse` on an object to find it.!
  318. !Finder class methodsFor: 'finding'!
  319. findClass: aClass
  320. ^ self current findClass: aClass
  321. !
  322. findMethod: aCompiledMethod
  323. ^ self current findMethod: aCompiledMethod
  324. !
  325. findString: aString
  326. ^ self current findString: aString
  327. ! !
  328. Service subclass: #Inspector
  329. instanceVariableNames: ''
  330. package: 'Platform-Services'!
  331. !Inspector commentStamp!
  332. I am the service responsible for inspecting objects.
  333. The default inspector object is the transcript.!
  334. !Inspector class methodsFor: 'inspecting'!
  335. inspect: anObject
  336. ^ self current inspect: anObject
  337. ! !
  338. Service subclass: #Platform
  339. instanceVariableNames: ''
  340. package: 'Platform-Services'!
  341. !Platform commentStamp!
  342. I am bridge to JS environment.
  343. ## API
  344. Platform globals. "JS global object"
  345. Platform newXHR "new XMLHttpRequest() or its shim"!
  346. !Platform class methodsFor: 'accessing'!
  347. globals
  348. ^ self current globals
  349. !
  350. newXhr
  351. ^ self current newXhr
  352. ! !
  353. Service subclass: #ProgressHandler
  354. instanceVariableNames: ''
  355. package: 'Platform-Services'!
  356. !ProgressHandler commentStamp!
  357. I am used to manage progress in collection iterations, see `SequenceableCollection >> #do:displayingProgress:`.
  358. Registered instances must implement `#do:on:displaying:`.
  359. The default behavior is to simply iterate over the collection, using `NullProgressHandler`.!
  360. !ProgressHandler class methodsFor: 'progress handling'!
  361. do: aBlock on: aCollection displaying: aString
  362. self current do: aBlock on: aCollection displaying: aString
  363. ! !
  364. Service subclass: #Terminal
  365. instanceVariableNames: ''
  366. package: 'Platform-Services'!
  367. !Terminal commentStamp!
  368. I am UI interface service.
  369. ## API
  370. Terminal alert: 'Hey, there is a problem'.
  371. Terminal confirm: 'Affirmative?'.
  372. Terminal prompt: 'Your name:'.!
  373. !Terminal class methodsFor: 'dialogs'!
  374. alert: aString
  375. ^ self current alert: aString
  376. !
  377. confirm: aString
  378. ^ self current confirm: aString
  379. !
  380. prompt: aString
  381. ^ self current prompt: aString
  382. !
  383. prompt: aString default: defaultString
  384. ^ self current prompt: aString default: defaultString
  385. ! !
  386. Service subclass: #Transcript
  387. instanceVariableNames: ''
  388. package: 'Platform-Services'!
  389. !Transcript commentStamp!
  390. I am a facade for Transcript actions.
  391. I delegate actions to the currently registered transcript.
  392. ## API
  393. Transcript
  394. show: 'hello world';
  395. cr;
  396. show: anObject.!
  397. !Transcript class methodsFor: 'instance creation'!
  398. open
  399. self current open
  400. ! !
  401. !Transcript class methodsFor: 'printing'!
  402. clear
  403. self current clear
  404. !
  405. cr
  406. self current show: String cr
  407. !
  408. inspect: anObject
  409. self show: anObject
  410. !
  411. show: anObject
  412. self current show: anObject
  413. ! !
  414. !AssociativeCollection methodsFor: '*Platform-Services'!
  415. inspectOn: anInspector
  416. | variables |
  417. variables := Dictionary new.
  418. variables at: '#self' put: self.
  419. variables at: '#keys' put: self keys.
  420. self keysAndValuesDo: [ :key :value |
  421. variables at: key put: value ].
  422. anInspector
  423. setLabel: self printString;
  424. setVariables: variables
  425. ! !
  426. !Collection methodsFor: '*Platform-Services'!
  427. inspectOn: anInspector
  428. | variables |
  429. variables := Dictionary new.
  430. variables at: '#self' put: self.
  431. self withIndexDo: [ :each :i |
  432. variables at: i put: each ].
  433. anInspector
  434. setLabel: self printString;
  435. setVariables: variables
  436. ! !
  437. !Date methodsFor: '*Platform-Services'!
  438. inspectOn: anInspector
  439. | variables |
  440. variables := Dictionary new.
  441. variables at: '#self' put: self.
  442. variables at: '#year' put: self year.
  443. variables at: '#month' put: self month.
  444. variables at: '#day' put: self day.
  445. variables at: '#hours' put: self hours.
  446. variables at: '#minutes' put: self minutes.
  447. variables at: '#seconds' put: self seconds.
  448. variables at: '#milliseconds' put: self milliseconds.
  449. anInspector
  450. setLabel: self printString;
  451. setVariables: variables
  452. ! !
  453. !JSObjectProxy methodsFor: '*Platform-Services'!
  454. inspectOn: anInspector
  455. | variables |
  456. variables := Dictionary new.
  457. variables at: '#self' put: self jsObject.
  458. anInspector setLabel: self printString.
  459. JSObjectProxy addObjectVariablesTo: variables ofProxy: self.
  460. anInspector setVariables: variables
  461. ! !
  462. !MethodContext methodsFor: '*Platform-Services'!
  463. inspectOn: anInspector
  464. | variables |
  465. variables := Dictionary new.
  466. variables at: '#self' put: self.
  467. variables at: '#home' put: self home.
  468. variables at: '#receiver' put: self receiver.
  469. variables at: '#selector' put: self selector.
  470. variables at: '#locals' put: self locals.
  471. self class instanceVariableNames do: [ :each |
  472. variables at: each put: (self instVarAt: each) ].
  473. anInspector
  474. setLabel: self printString;
  475. setVariables: variables
  476. ! !
  477. !Object methodsFor: '*Platform-Services'!
  478. inspectOn: anInspector
  479. | variables |
  480. variables := Dictionary new.
  481. variables at: '#self' put: self.
  482. self class allInstanceVariableNames do: [ :each |
  483. variables at: each put: (self instVarAt: each) ].
  484. anInspector
  485. setLabel: self printString;
  486. setVariables: variables
  487. ! !
  488. !SequenceableCollection methodsFor: '*Platform-Services'!
  489. do: aBlock displayingProgress: aString
  490. ProgressHandler
  491. do: aBlock
  492. on: self
  493. displaying: aString
  494. ! !
  495. !Set methodsFor: '*Platform-Services'!
  496. inspectOn: anInspector
  497. | variables i |
  498. variables := Dictionary new.
  499. variables at: '#self' put: self.
  500. i := 1.
  501. self do: [ :each |
  502. variables at: i put: each.
  503. i := i + 1 ].
  504. anInspector
  505. setLabel: self printString;
  506. setVariables: variables
  507. ! !
  508. !String methodsFor: '*Platform-Services'!
  509. inspectOn: anInspector
  510. | label |
  511. super inspectOn: anInspector.
  512. self printString size > 30
  513. ifTrue: [ label := (self printString copyFrom: 1 to: 30), '...''' ]
  514. ifFalse: [ label := self printString ].
  515. anInspector setLabel: label
  516. ! !