Kernel-Infrastructure.st 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. Smalltalk current createPackage: 'Kernel-Infrastructure'!
  2. nil subclass: #AbstractProxy
  3. instanceVariableNames: ''
  4. package: 'Kernel-Infrastructure'!
  5. !AbstractProxy commentStamp!
  6. I provide a basic set of methods for proxies handling `#doesNotUnderstand:` so that inspectors, debuggers, etc. won't fail.!
  7. !AbstractProxy methodsFor: 'accessing'!
  8. class
  9. <return self.klass>
  10. !
  11. identityHash
  12. <
  13. var hash=self.identityHash;
  14. if (hash) return hash;
  15. hash=smalltalk.nextId();
  16. Object.defineProperty(self, 'identityHash', {value:hash});
  17. return hash;
  18. >
  19. !
  20. instVarAt: aString
  21. < return self['@'+aString] >
  22. !
  23. instVarAt: aString put: anObject
  24. < self['@' + aString] = anObject >
  25. !
  26. yourself
  27. ^ self
  28. ! !
  29. !AbstractProxy methodsFor: 'converting'!
  30. asString
  31. ^ self printString
  32. ! !
  33. !AbstractProxy methodsFor: 'error handling'!
  34. doesNotUnderstand: aMessage
  35. MessageNotUnderstood new
  36. receiver: self;
  37. message: aMessage;
  38. signal
  39. ! !
  40. !AbstractProxy methodsFor: 'initialization'!
  41. initialize
  42. ! !
  43. !AbstractProxy methodsFor: 'inspecting'!
  44. inspect
  45. InspectorHandler inspect: self
  46. !
  47. inspectOn: anInspector
  48. ! !
  49. !AbstractProxy methodsFor: 'message handling'!
  50. perform: aString
  51. ^ self perform: aString withArguments: #()
  52. !
  53. perform: aString withArguments: aCollection
  54. <return smalltalk.send(self, aString._asSelector(), aCollection)>
  55. ! !
  56. !AbstractProxy methodsFor: 'printing'!
  57. printOn: aStream
  58. aStream nextPutAll: (self class name first isVowel
  59. ifTrue: [ 'an ' ]
  60. ifFalse: [ 'a ' ]).
  61. aStream nextPutAll: self class name
  62. !
  63. printString
  64. ^ String streamContents: [ :str |
  65. self printOn: str ]
  66. ! !
  67. !AbstractProxy class methodsFor: 'helios'!
  68. heliosClass
  69. ^ 'class'
  70. ! !
  71. !AbstractProxy class methodsFor: 'initialization'!
  72. initialize
  73. ! !
  74. AbstractProxy subclass: #JSObjectProxy
  75. instanceVariableNames: 'jsObject'
  76. package: 'Kernel-Infrastructure'!
  77. !JSObjectProxy commentStamp!
  78. I handle sending messages to JavaScript objects, making JavaScript object accessing from Amber fully transparent.
  79. My instances make intensive use of `#doesNotUnderstand:`.
  80. My instances are automatically created by Amber whenever a message is sent to a JavaScript object.
  81. ## Usage examples
  82. JSObjectProxy objects are instanciated by Amber when a Smalltalk message is sent to a JavaScript object.
  83. window alert: 'hello world'.
  84. window inspect.
  85. (window jQuery: 'body') append: 'hello world'
  86. 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.
  87. ## Message conversion rules
  88. - `someUser name` becomes `someUser.name`
  89. - `someUser name: 'John'` becomes `someUser name = "John"`
  90. - `console log: 'hello world'` becomes `console.log('hello world')`
  91. - `(window jQuery: 'foo') css: 'background' color: 'red'` becomes `window.jQuery('foo').css('background', 'red')`
  92. __Note:__ For keyword-based messages, only the first keyword is kept: `window foo: 1 bar: 2` is equivalent to `window foo: 1 baz: 2`.!
  93. !JSObjectProxy methodsFor: 'accessing'!
  94. at: aString
  95. <return self['@jsObject'][aString]>
  96. !
  97. at: aString ifAbsent: aBlock
  98. "return the aString property or evaluate aBlock if the property is not defined on the object"
  99. <
  100. var obj = self['@jsObject'];
  101. return aString in obj ? obj[aString] : aBlock._value();
  102. >
  103. !
  104. at: aString ifPresent: aBlock
  105. "return the evaluation of aBlock with the value if the property is defined or return nil"
  106. <
  107. var obj = self['@jsObject'];
  108. return aString in obj ? aBlock._value_(obj[aString]) : nil;
  109. >
  110. !
  111. at: aString ifPresent: aBlock ifAbsent: anotherBlock
  112. "return the evaluation of aBlock with the value if the property is defined
  113. or return value of anotherBlock"
  114. <
  115. var obj = self['@jsObject'];
  116. return aString in obj ? aBlock._value_(obj[aString]) : anotherBlock._value();
  117. >
  118. !
  119. at: aString put: anObject
  120. <self['@jsObject'][aString] = anObject>
  121. !
  122. jsObject
  123. ^ jsObject
  124. !
  125. jsObject: aJSObject
  126. jsObject := aJSObject
  127. !
  128. lookupProperty: aString
  129. "Looks up a property in JS object.
  130. Answer the property if it is present, or nil if it is not present."
  131. <return aString in self._jsObject() ? aString : nil>
  132. ! !
  133. !JSObjectProxy methodsFor: 'enumerating'!
  134. asJSON
  135. "Answers the receiver in a stringyfy-friendly fashion"
  136. ^ jsObject
  137. !
  138. keysAndValuesDo: aBlock
  139. <
  140. var o = self['@jsObject'];
  141. for(var i in o) {
  142. aBlock._value_value_(i, o[i]);
  143. }
  144. >
  145. ! !
  146. !JSObjectProxy methodsFor: 'printing'!
  147. printOn: aStream
  148. aStream nextPutAll: self printString
  149. !
  150. printString
  151. <
  152. var js = self['@jsObject'];
  153. return js.toString
  154. ? js.toString()
  155. : Object.prototype.toString.call(js)
  156. >
  157. ! !
  158. !JSObjectProxy methodsFor: 'proxy'!
  159. addObjectVariablesTo: aDictionary
  160. <
  161. for(var i in self['@jsObject']) {
  162. aDictionary._at_put_(i, self['@jsObject'][i]);
  163. }
  164. >
  165. !
  166. doesNotUnderstand: aMessage
  167. ^ (self lookupProperty: aMessage selector asJavaScriptSelector)
  168. ifNil: [ super doesNotUnderstand: aMessage ]
  169. ifNotNil: [ :jsSelector |
  170. self
  171. forwardMessage: jsSelector
  172. withArguments: aMessage arguments ]
  173. !
  174. forwardMessage: aString withArguments: anArray
  175. <
  176. return smalltalk.send(self._jsObject(), aString, anArray);
  177. >
  178. !
  179. inspectOn: anInspector
  180. | variables |
  181. variables := Dictionary new.
  182. variables at: '#self' put: self jsObject.
  183. anInspector setLabel: self printString.
  184. self addObjectVariablesTo: variables.
  185. anInspector setVariables: variables
  186. ! !
  187. !JSObjectProxy class methodsFor: 'instance creation'!
  188. on: aJSObject
  189. ^ self new
  190. jsObject: aJSObject;
  191. yourself
  192. ! !
  193. Object subclass: #InspectorHandler
  194. instanceVariableNames: ''
  195. package: 'Kernel-Infrastructure'!
  196. !InspectorHandler commentStamp!
  197. I am responsible for inspecting object.
  198. My class-side `inspector` inst var holds the current inspector I'm delegating object inspection to.
  199. The default inspector object is the transcript.!
  200. InspectorHandler class instanceVariableNames: 'inspector'!
  201. !InspectorHandler class methodsFor: 'accessing'!
  202. inspector
  203. ^ inspector ifNil: [ inspector := Transcript ]
  204. ! !
  205. !InspectorHandler class methodsFor: 'registration'!
  206. inspect: anObject
  207. ^ self inspector inspect: anObject
  208. !
  209. register: anInspector
  210. inspector := anInspector
  211. ! !
  212. Object subclass: #InterfacingObject
  213. instanceVariableNames: ''
  214. package: 'Kernel-Infrastructure'!
  215. !InterfacingObject commentStamp!
  216. 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`.
  217. ## API
  218. self alert: 'Hey, there is a problem'.
  219. self confirm: 'Affirmative?'.
  220. self prompt: 'Your name:'.
  221. self ajax: #{
  222. 'url' -> '/patch.js'. 'type' -> 'GET'. dataType->'script'
  223. }.!
  224. !InterfacingObject methodsFor: 'actions'!
  225. ajax: anObject
  226. ^ PlatformInterface ajax: anObject
  227. !
  228. alert: aString
  229. ^ PlatformInterface alert: aString
  230. !
  231. confirm: aString
  232. ^ PlatformInterface confirm: aString
  233. !
  234. prompt: aString
  235. ^ PlatformInterface prompt: aString
  236. ! !
  237. InterfacingObject subclass: #Environment
  238. instanceVariableNames: ''
  239. package: 'Kernel-Infrastructure'!
  240. !Environment commentStamp!
  241. I provide an unified entry point to manipulate Amber packages, classes and methods.
  242. Typical use cases include IDEs, remote access and restricting browsing.!
  243. !Environment methodsFor: 'accessing'!
  244. allSelectors
  245. ^ (Smalltalk current at: 'allSelectors') value
  246. !
  247. availableClassNames
  248. ^ Smalltalk current classes
  249. collect: [ :each | each name ]
  250. !
  251. availablePackageNames
  252. ^ Smalltalk current packages
  253. collect: [ :each | each name ]
  254. !
  255. availableProtocolsFor: aClass
  256. | protocols |
  257. protocols := aClass protocols.
  258. aClass superclass ifNotNil: [ protocols addAll: (self availableProtocolsFor: aClass superclass) ].
  259. ^ protocols asSet asArray
  260. !
  261. classBuilder
  262. ^ ClassBuilder new
  263. !
  264. classNamed: aString
  265. ^ (Smalltalk current at: aString asSymbol)
  266. ifNil: [ self error: 'Invalid class name' ]
  267. !
  268. classes
  269. ^ Smalltalk current classes
  270. !
  271. doItReceiver
  272. ^ DoIt new
  273. !
  274. packages
  275. ^ Smalltalk current packages
  276. !
  277. systemAnnouncer
  278. ^ (Smalltalk current at: #SystemAnnouncer) current
  279. ! !
  280. !Environment methodsFor: 'actions'!
  281. commitPackage: aPackage
  282. aPackage commit
  283. !
  284. copyClass: aClass to: aClassName
  285. (Smalltalk current at: aClassName)
  286. ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].
  287. ClassBuilder new copyClass: aClass named: aClassName
  288. !
  289. eval: aString on: aReceiver
  290. | compiler |
  291. compiler := Compiler new.
  292. [ compiler parseExpression: aString ] on: Error do: [ :ex |
  293. ^ self alert: ex messageText ].
  294. ^ compiler evaluateExpression: aString on: aReceiver
  295. !
  296. inspect: anObject
  297. InspectorHandler inspector inspect: anObject
  298. !
  299. moveClass: aClass toPackage: aPackageName
  300. | package |
  301. package := Package named: aPackageName.
  302. package ifNil: [ self error: 'Invalid package name' ].
  303. package == aClass package ifTrue: [ ^ self ].
  304. aClass package: package
  305. !
  306. moveMethod: aMethod toClass: aClassName
  307. | destinationClass |
  308. destinationClass := Smalltalk current at: aClassName asSymbol.
  309. destinationClass ifNil: [ self error: 'Invalid class name' ].
  310. destinationClass == aMethod methodClass ifTrue: [ ^ self ].
  311. destinationClass
  312. compile: aMethod source
  313. category: aMethod protocol.
  314. aMethod methodClass
  315. removeCompiledMethod: aMethod
  316. !
  317. moveMethod: aMethod toProtocol: aProtocol
  318. aMethod category: aProtocol
  319. !
  320. registerErrorHandler: anErrorHandler
  321. ErrorHandler setCurrent: anErrorHandler
  322. !
  323. registerInspector: anInspector
  324. InspectorHandler register: anInspector
  325. !
  326. registerProgressHandler: aProgressHandler
  327. ProgressHandler setCurrent: aProgressHandler
  328. !
  329. removeClass: aClass
  330. Smalltalk current removeClass: aClass
  331. !
  332. removeMethod: aMethod
  333. aMethod methodClass removeCompiledMethod: aMethod
  334. !
  335. removeProtocol: aString from: aClass
  336. (aClass methods
  337. select: [ :each | each protocol = aString ])
  338. do: [ :each | aClass removeCompiledMethod: each ]
  339. !
  340. renameClass: aClass to: aClassName
  341. (Smalltalk current at: aClassName)
  342. ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].
  343. ClassBuilder new renameClass: aClass to: aClassName
  344. !
  345. renameProtocol: aString to: anotherString in: aClass
  346. (aClass methods
  347. select: [ :each | each protocol = aString ])
  348. do: [ :each | each protocol: anotherString ]
  349. !
  350. setClassCommentOf: aClass to: aString
  351. aClass comment: aString
  352. ! !
  353. !Environment methodsFor: 'compiling'!
  354. addInstVarNamed: aString to: aClass
  355. self classBuilder
  356. addSubclassOf: aClass superclass
  357. named: aClass name
  358. instanceVariableNames: (aClass instanceVariableNames copy add: aString; yourself)
  359. package: aClass package name
  360. !
  361. compileClassComment: aString for: aClass
  362. aClass comment: aString
  363. !
  364. compileClassDefinition: aString
  365. self eval: aString on: DoIt new
  366. !
  367. compileMethod: sourceCode for: class protocol: protocol
  368. ^ class
  369. compile: sourceCode
  370. category: protocol
  371. ! !
  372. !Environment methodsFor: 'error handling'!
  373. evaluate: aBlock on: anErrorClass do: exceptionBlock
  374. "Evaluate a block and catch exceptions happening on the environment stack"
  375. self try: aBlock catch: [ :exception |
  376. (exception isKindOf: (self classNamed: anErrorClass name))
  377. ifTrue: [ exceptionBlock value: exception ]
  378. ifFalse: [ exception signal ] ]
  379. ! !
  380. Object subclass: #Organizer
  381. instanceVariableNames: ''
  382. package: 'Kernel-Infrastructure'!
  383. !Organizer commentStamp!
  384. I represent categorization information.
  385. ## API
  386. Use `#addElement:` and `#removeElement:` to manipulate instances.!
  387. !Organizer methodsFor: 'accessing'!
  388. addElement: anObject
  389. <self.elements.addElement(anObject)>
  390. !
  391. elements
  392. ^ (self basicAt: 'elements') copy
  393. !
  394. removeElement: anObject
  395. <self.elements.removeElement(anObject)>
  396. ! !
  397. Organizer subclass: #ClassOrganizer
  398. instanceVariableNames: ''
  399. package: 'Kernel-Infrastructure'!
  400. !ClassOrganizer commentStamp!
  401. I am an organizer specific to classes. I hold method categorization information for classes.!
  402. !ClassOrganizer methodsFor: 'accessing'!
  403. addElement: aString
  404. super addElement: aString.
  405. SystemAnnouncer current announce: (ProtocolAdded new
  406. protocol: aString;
  407. theClass: self theClass;
  408. yourself)
  409. !
  410. removeElement: aString
  411. super removeElement: aString.
  412. SystemAnnouncer current announce: (ProtocolRemoved new
  413. protocol: aString;
  414. theClass: self theClass;
  415. yourself)
  416. !
  417. theClass
  418. < return self.theClass >
  419. ! !
  420. Organizer subclass: #PackageOrganizer
  421. instanceVariableNames: ''
  422. package: 'Kernel-Infrastructure'!
  423. !PackageOrganizer commentStamp!
  424. I am an organizer specific to packages. I hold classes categorization information.!
  425. Object subclass: #Package
  426. instanceVariableNames: 'transport'
  427. package: 'Kernel-Infrastructure'!
  428. !Package commentStamp!
  429. 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.
  430. 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.
  431. ## API
  432. Packages are manipulated through "Smalltalk current", like for example finding one based on a name or with `Package class >> #name` directly:
  433. Smalltalk current packageAt: 'Kernel'
  434. Package named: 'Kernel'
  435. 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.
  436. You can fetch a package from the server:
  437. Package load: 'Additional-Examples'!
  438. !Package methodsFor: 'accessing'!
  439. basicTransport
  440. "Answer the transport literal JavaScript object as setup in the JavaScript file, if any"
  441. <return self.transport>
  442. !
  443. definition
  444. ^ String streamContents: [ :stream |
  445. stream
  446. nextPutAll: self class name;
  447. nextPutAll: String lf, String tab;
  448. nextPutAll: ' named: ';
  449. nextPutAll: '''', self name, '''';
  450. nextPutAll: String lf, String tab;
  451. nextPutAll: ' transport: (';
  452. nextPutAll: self transport definition, ')' ]
  453. !
  454. name
  455. <return self.pkgName>
  456. !
  457. name: aString
  458. <self.pkgName = aString>
  459. !
  460. organization
  461. ^ self basicAt: 'organization'
  462. !
  463. transport
  464. ^ transport ifNil: [
  465. transport := (PackageTransport fromJson: self basicTransport)
  466. package: self;
  467. yourself ]
  468. !
  469. transport: aPackageTransport
  470. transport := aPackageTransport.
  471. aPackageTransport package: self
  472. ! !
  473. !Package methodsFor: 'classes'!
  474. classes
  475. ^ self organization elements asSet asArray
  476. !
  477. setupClasses
  478. self classes
  479. do: [ :each | ClassBuilder new setupClass: each ];
  480. do: [ :each | each initialize ]
  481. !
  482. sortedClasses
  483. "Answer all classes in the receiver, sorted by superclass/subclasses and by class name for common subclasses (Issue #143)."
  484. ^ self class sortedClasses: self classes
  485. ! !
  486. !Package methodsFor: 'dependencies'!
  487. loadDependencies
  488. "Returns list of packages that need to be loaded
  489. before loading this package."
  490. | classes packages |
  491. classes := self loadDependencyClasses.
  492. ^ (classes collect: [ :each | each package ]) asSet
  493. remove: self ifAbsent: [];
  494. yourself
  495. !
  496. loadDependencyClasses
  497. "Returns classes needed at the time of loading a package.
  498. These are all that are used to subclass
  499. and to define an extension method"
  500. | starCategoryName |
  501. starCategoryName := '*', self name.
  502. ^ (self classes collect: [ :each | each superclass ]) asSet
  503. remove: nil ifAbsent: [];
  504. addAll: (Smalltalk current classes select: [ :each | each protocols, each class protocols includes: starCategoryName ]);
  505. yourself
  506. ! !
  507. !Package methodsFor: 'printing'!
  508. printOn: aStream
  509. super printOn: aStream.
  510. aStream
  511. nextPutAll: ' (';
  512. nextPutAll: self name;
  513. nextPutAll: ')'
  514. ! !
  515. !Package methodsFor: 'testing'!
  516. isPackage
  517. ^ true
  518. ! !
  519. Package class instanceVariableNames: 'defaultCommitPathJs defaultCommitPathSt'!
  520. !Package class methodsFor: 'accessing'!
  521. named: aPackageName
  522. ^ Smalltalk current
  523. packageAt: aPackageName
  524. ifAbsent: [
  525. Smalltalk current createPackage: aPackageName ]
  526. !
  527. named: aPackageName ifAbsent: aBlock
  528. ^ Smalltalk current packageAt: aPackageName ifAbsent: aBlock
  529. !
  530. named: aPackageName transport: aTransport
  531. | package |
  532. package := self named: aPackageName.
  533. package transport: aTransport.
  534. ^ package
  535. ! !
  536. !Package class methodsFor: 'sorting'!
  537. sortedClasses: classes
  538. "Answer classes, sorted by superclass/subclasses and by class name for common subclasses (Issue #143)"
  539. | children others nodes expandedClasses |
  540. children := #().
  541. others := #().
  542. classes do: [ :each |
  543. (classes includes: each superclass)
  544. ifFalse: [ children add: each ]
  545. ifTrue: [ others add: each ]].
  546. nodes := children collect: [ :each |
  547. ClassSorterNode on: each classes: others level: 0 ].
  548. nodes := nodes sorted: [ :a :b | a theClass name <= b theClass name ].
  549. expandedClasses := Array new.
  550. nodes do: [ :aNode |
  551. aNode traverseClassesWith: expandedClasses ].
  552. ^ expandedClasses
  553. ! !
  554. Object subclass: #PlatformInterface
  555. instanceVariableNames: ''
  556. package: 'Kernel-Infrastructure'!
  557. !PlatformInterface commentStamp!
  558. I am single entry point to UI and environment interface.
  559. My `initialize` tries several options (for now, browser environment only) to set myself up.
  560. ## API
  561. PlatformInterface alert: 'Hey, there is a problem'.
  562. PlatformInterface confirm: 'Affirmative?'.
  563. PlatformInterface prompt: 'Your name:'.
  564. PlatformInterface ajax: #{
  565. 'url' -> '/patch.js'. 'type' -> 'GET'. dataType->'script'
  566. }.!
  567. PlatformInterface class instanceVariableNames: 'worker'!
  568. !PlatformInterface class methodsFor: 'accessing'!
  569. globals
  570. <return (new Function('return this'))();>
  571. !
  572. setWorker: anObject
  573. worker := anObject
  574. ! !
  575. !PlatformInterface class methodsFor: 'actions'!
  576. ajax: anObject
  577. ^ worker
  578. ifNotNil: [ worker ajax: anObject ]
  579. ifNil: [ self error: 'ajax: not available' ]
  580. !
  581. alert: aString
  582. ^ worker
  583. ifNotNil: [ worker alert: aString ]
  584. ifNil: [ self error: 'alert: not available' ]
  585. !
  586. confirm: aString
  587. ^ worker
  588. ifNotNil: [ worker confirm: aString ]
  589. ifNil: [ self error: 'confirm: not available' ]
  590. !
  591. existsGlobal: aString
  592. ^ PlatformInterface globals
  593. at: aString
  594. ifPresent: [ true ]
  595. ifAbsent: [ false ]
  596. !
  597. prompt: aString
  598. ^ worker
  599. ifNotNil: [ worker prompt: aString ]
  600. ifNil: [ self error: 'prompt: not available' ]
  601. ! !
  602. !PlatformInterface class methodsFor: 'initialization'!
  603. initialize
  604. | candidate |
  605. super initialize.
  606. BrowserInterface ifNotNil: [
  607. candidate := BrowserInterface new.
  608. candidate isAvailable ifTrue: [ self setWorker: candidate. ^ self ]
  609. ]
  610. ! !
  611. Object subclass: #ProgressHandler
  612. instanceVariableNames: ''
  613. package: 'Kernel-Infrastructure'!
  614. !ProgressHandler commentStamp!
  615. I am used to manage progress in collection iterations, see `SequenceableCollection >> #do:displayingProgress:`.
  616. Subclasses of can register themselves as the current handler with
  617. `ProgressHandler class >> register`.
  618. The default behavior is to simply iterate over the collection.!
  619. !ProgressHandler methodsFor: 'progress handling'!
  620. do: aBlock on: aCollection displaying: aString
  621. aCollection do: aBlock
  622. ! !
  623. ProgressHandler class instanceVariableNames: 'current'!
  624. !ProgressHandler class methodsFor: 'accessing'!
  625. current
  626. ^ current ifNil: [ current := self new ]
  627. !
  628. setCurrent: anHandler
  629. current := anHandler
  630. ! !
  631. !ProgressHandler class methodsFor: 'initialization'!
  632. initialize
  633. self register
  634. !
  635. register
  636. ProgressHandler setCurrent: self new
  637. ! !
  638. Object subclass: #Smalltalk
  639. instanceVariableNames: ''
  640. package: 'Kernel-Infrastructure'!
  641. !Smalltalk commentStamp!
  642. I represent the global JavaScript variable `smalltalk` declared in `js/boot.js`.
  643. ## API
  644. I have only one instance, accessed with class-side method `#current`.
  645. The `smalltalk` object holds all class and packages defined in the system.
  646. ## Classes
  647. Classes can be accessed using the following methods:
  648. - `#classes` answers the full list of Smalltalk classes in the system
  649. - `#at:` answers a specific class or `nil`
  650. ## Packages
  651. Packages can be accessed using the following methods:
  652. - `#packages` answers the full list of packages
  653. - `#packageAt:` answers a specific package or `nil`
  654. ## Parsing
  655. The `#parse:` method is used to parse Amber source code.
  656. It requires the `Compiler` package and the `js/parser.js` parser file in order to work.!
  657. !Smalltalk methodsFor: 'accessing'!
  658. at: aString
  659. ^ self basicAt: aString
  660. !
  661. at: aKey ifAbsent: aBlock
  662. ^ (self includesKey: aKey)
  663. ifTrue: [ self at: aKey ]
  664. ifFalse: aBlock
  665. !
  666. at: aString put: anObject
  667. ^ self basicAt: aString put: anObject
  668. !
  669. includesKey: aKey
  670. <return self.hasOwnProperty(aKey)>
  671. !
  672. parse: aString
  673. | result |
  674. self
  675. try: [ result := self basicParse: aString ]
  676. catch: [ :ex | (self parseError: ex parsing: aString) signal ].
  677. ^ result
  678. source: aString;
  679. yourself
  680. !
  681. pseudoVariableNames
  682. ^ #('self' 'super' 'nil' 'true' 'false' 'thisContext')
  683. !
  684. readJSObject: anObject
  685. <return self.readJSObject(anObject)>
  686. !
  687. reservedWords
  688. "JavaScript reserved words"
  689. <return self.reservedWords>
  690. !
  691. version
  692. "Answer the version string of Amber"
  693. ^ '0.13.0-pre'
  694. ! !
  695. !Smalltalk methodsFor: 'accessing amd'!
  696. amdRequire
  697. ^ self at: 'amdRequire'
  698. !
  699. defaultAmdNamespace
  700. ^ self at: 'defaultAmdNamespace'
  701. !
  702. defaultAmdNamespace: aString
  703. self at: 'defaultAmdNamespace' put: aString
  704. ! !
  705. !Smalltalk methodsFor: 'classes'!
  706. classes
  707. <return self.classes()>
  708. !
  709. removeClass: aClass
  710. aClass isMetaclass ifTrue: [ self error: aClass asString, ' is a Metaclass and cannot be removed!!' ].
  711. self deleteClass: aClass.
  712. SystemAnnouncer current
  713. announce: (ClassRemoved new
  714. theClass: aClass;
  715. yourself)
  716. ! !
  717. !Smalltalk methodsFor: 'error handling'!
  718. asSmalltalkException: anObject
  719. "A JavaScript exception may be thrown.
  720. We then need to convert it back to a Smalltalk object"
  721. ^ ((self isSmalltalkObject: anObject) and: [ anObject isKindOf: Error ])
  722. ifTrue: [ anObject ]
  723. ifFalse: [ JavaScriptException on: anObject ]
  724. !
  725. parseError: anException parsing: aString
  726. ^ ParseError new messageText: 'Parse error on line ', (anException basicAt: 'line') ,' column ' , (anException basicAt: 'column') ,' : Unexpected character ', (anException basicAt: 'found')
  727. ! !
  728. !Smalltalk methodsFor: 'globals'!
  729. addGlobalJsVariable: aString
  730. self globalJsVariables add: aString
  731. !
  732. deleteGlobalJsVariable: aString
  733. self globalJsVariables remove: aString ifAbsent:[]
  734. !
  735. globalJsVariables
  736. "Array of global JavaScript variables"
  737. <return self.globalJsVariables>
  738. ! !
  739. !Smalltalk methodsFor: 'packages'!
  740. createPackage: packageName
  741. | package announcement |
  742. package := self basicCreatePackage: packageName.
  743. announcement := PackageAdded new
  744. package: package;
  745. yourself.
  746. SystemAnnouncer current announce: announcement.
  747. ^ package
  748. !
  749. packageAt: packageName
  750. <return self.packages[ packageName]>
  751. !
  752. packageAt: packageName ifAbsent: aBlock
  753. ^ (self packageAt: packageName) ifNil: aBlock
  754. !
  755. packages
  756. "Return all Package instances in the system."
  757. <
  758. var packages = [];
  759. for(var key in self.packages) {
  760. packages.push(self.packages[key]);
  761. }
  762. return packages;
  763. >
  764. !
  765. removePackage: packageName
  766. "Removes a package and all its classes."
  767. | pkg |
  768. pkg := self packageAt: packageName ifAbsent: [ self error: 'Missing package: ', packageName ].
  769. pkg classes do: [ :each |
  770. self removeClass: each ].
  771. self deletePackage: packageName
  772. !
  773. renamePackage: packageName to: newName
  774. "Rename a package."
  775. | pkg |
  776. pkg := self packageAt: packageName ifAbsent: [ self error: 'Missing package: ', packageName ].
  777. (self packageAt: newName) ifNotNil: [ self error: 'Already exists a package called: ', newName ].
  778. (self at: 'packages') at: newName put: pkg.
  779. pkg name: newName.
  780. self deletePackage: packageName.
  781. ! !
  782. !Smalltalk methodsFor: 'private'!
  783. basicCreatePackage: packageName
  784. "Create and bind a new bare package with given name and return it."
  785. <return smalltalk.addPackage(packageName)>
  786. !
  787. basicParse: aString
  788. <return smalltalk.parser.parse(aString)>
  789. !
  790. createPackage: packageName properties: aDict
  791. "Needed to import .st files: they begin with this call."
  792. self deprecatedAPI.
  793. aDict isEmpty ifFalse: [ self error: 'createPackage:properties: called with nonempty properties' ].
  794. ^ self createPackage: packageName
  795. !
  796. deleteClass: aClass
  797. "Deletes a class by deleting its binding only. Use #removeClass instead"
  798. <self.removeClass(aClass)>
  799. !
  800. deletePackage: packageName
  801. "Deletes a package by deleting its binding, but does not check if it contains classes etc.
  802. To remove a package, use #removePackage instead."
  803. <delete self.packages[ packageName]>
  804. ! !
  805. !Smalltalk methodsFor: 'testing'!
  806. isSmalltalkObject: anObject
  807. "Consider anObject a Smalltalk object if it has a 'klass' property.
  808. Note that this may be unaccurate"
  809. <return typeof anObject.klass !!== 'undefined'>
  810. ! !
  811. !Smalltalk class methodsFor: 'accessing'!
  812. current
  813. <return smalltalk>
  814. ! !
  815. !SequenceableCollection methodsFor: '*Kernel-Infrastructure'!
  816. do: aBlock displayingProgress: aString
  817. ProgressHandler current
  818. do: aBlock on: self displaying: aString
  819. ! !
  820. !String methodsFor: '*Kernel-Infrastructure'!
  821. asJavaScriptSelector
  822. "Return first keyword of the selector, without trailing colon."
  823. ^ self replace: '^([a-zA-Z0-9]*).*$' with: '$1'
  824. ! !