Kernel-Methods.st 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. Smalltalk createPackage: 'Kernel-Methods'!
  2. Object subclass: #BlockClosure
  3. instanceVariableNames: ''
  4. package: 'Kernel-Methods'!
  5. !BlockClosure commentStamp!
  6. I represent a lexical closure.
  7. I am is directly mapped to JavaScript Function.
  8. ## API
  9. 1. Evaluation
  10. My instances get evaluated with the `#value*` methods in the 'evaluating' protocol.
  11. Example: ` [ :x | x + 1 ] value: 3 "Answers 4" `
  12. 2. Control structures
  13. Blocks are used (together with `Boolean`) for control structures (methods in the `controlling` protocol).
  14. Example: `aBlock whileTrue: [ ... ]`
  15. 3. Error handling
  16. I provide the `#on:do:` method for handling exceptions.
  17. Example: ` aBlock on: MessageNotUnderstood do: [ :ex | ... ] `!
  18. !BlockClosure methodsFor: 'accessing'!
  19. compiledSource
  20. <return self.toString()>
  21. !
  22. numArgs
  23. <return self.length>
  24. !
  25. receiver
  26. ^ nil
  27. ! !
  28. !BlockClosure methodsFor: 'controlling'!
  29. whileFalse
  30. self whileFalse: []
  31. !
  32. whileFalse: aBlock
  33. <while(!!smalltalk.assert(self._value())) {aBlock._value()}>
  34. !
  35. whileTrue
  36. self whileTrue: []
  37. !
  38. whileTrue: aBlock
  39. <while(smalltalk.assert(self._value())) {aBlock._value()}>
  40. ! !
  41. !BlockClosure methodsFor: 'converting'!
  42. asCompiledMethod: aString
  43. <return smalltalk.method({selector:aString, fn:self});>
  44. !
  45. currySelf
  46. "Transforms [ :selfarg :x :y | stcode ] block
  47. which represents JS function (selfarg, x, y, ...) {jscode}
  48. into function (x, y, ...) {jscode} that takes selfarg from 'this'.
  49. IOW, it is usable as JS method and first arg takes the receiver."
  50. <
  51. return function () {
  52. var args = [ this ];
  53. args.push.apply(args, arguments);
  54. return self.apply(null, args);
  55. }
  56. >
  57. ! !
  58. !BlockClosure methodsFor: 'error handling'!
  59. on: anErrorClass do: aBlock
  60. "All exceptions thrown in the Smalltalk stack are cought.
  61. Convert all JS exceptions to JavaScriptException instances."
  62. ^ self try: self catch: [ :error | | smalltalkError |
  63. smalltalkError := Smalltalk asSmalltalkException: error.
  64. (smalltalkError isKindOf: anErrorClass)
  65. ifTrue: [ aBlock value: smalltalkError ]
  66. ifFalse: [ smalltalkError resignal ] ]
  67. ! !
  68. !BlockClosure methodsFor: 'evaluating'!
  69. applyTo: anObject arguments: aCollection
  70. <return self.apply(anObject, aCollection)>
  71. !
  72. ensure: aBlock
  73. <try{return self._value()}finally{aBlock._value()}>
  74. !
  75. new
  76. "Use the receiver as a JS constructor.
  77. *Do not* use this method to instanciate Smalltalk objects!!"
  78. <return new self()>
  79. !
  80. newValue: anObject
  81. ^ self newWithValues: { anObject }
  82. !
  83. newValue: anObject value: anObject2
  84. ^ self newWithValues: { anObject. anObject2 }.
  85. !
  86. newValue: anObject value: anObject2 value: anObject3
  87. ^ self newWithValues: { anObject. anObject2. anObject3 }.
  88. !
  89. newWithValues: aCollection
  90. "Simulates JS new operator by combination of Object.create and .apply"
  91. <
  92. var object = Object.create(self.prototype);
  93. var result = self.apply(object, aCollection);
  94. return typeof result === "object" ? result : object;
  95. >
  96. !
  97. timeToRun
  98. "Answer the number of milliseconds taken to execute this block."
  99. ^ Date millisecondsToRun: self
  100. !
  101. value
  102. <return self();>
  103. !
  104. value: anArg
  105. <return self(anArg);>
  106. !
  107. value: firstArg value: secondArg
  108. <return self(firstArg, secondArg);>
  109. !
  110. value: firstArg value: secondArg value: thirdArg
  111. <return self(firstArg, secondArg, thirdArg);>
  112. !
  113. valueWithPossibleArguments: aCollection
  114. <return self.apply(null, aCollection);>
  115. ! !
  116. !BlockClosure methodsFor: 'timeout/interval'!
  117. fork
  118. ForkPool default fork: self
  119. !
  120. valueWithInterval: aNumber
  121. <
  122. var interval = setInterval(self, aNumber);
  123. return globals.Timeout._on_(interval);
  124. >
  125. !
  126. valueWithTimeout: aNumber
  127. <
  128. var timeout = setTimeout(self, aNumber);
  129. return globals.Timeout._on_(timeout);
  130. >
  131. ! !
  132. Object subclass: #CompiledMethod
  133. instanceVariableNames: ''
  134. package: 'Kernel-Methods'!
  135. !CompiledMethod commentStamp!
  136. I represent a class method of the system. I hold the source and compiled code of a class method.
  137. ## API
  138. My instances can be accessed using `Behavior >> #methodAt:`
  139. Object methodAt: 'asString'
  140. Source code access:
  141. (String methodAt: 'lines') source
  142. Referenced classes:
  143. (String methodAt: 'lines') referencedClasses
  144. Messages sent from an instance:
  145. (String methodAt: 'lines') messageSends!
  146. !CompiledMethod methodsFor: 'accessing'!
  147. arguments
  148. <return self.args || []>
  149. !
  150. category
  151. ^ self protocol
  152. !
  153. fn
  154. ^ self basicAt: 'fn'
  155. !
  156. fn: aBlock
  157. self basicAt: 'fn' put: aBlock
  158. !
  159. messageSends
  160. ^ self basicAt: 'messageSends'
  161. !
  162. methodClass
  163. ^ self basicAt: 'methodClass'
  164. !
  165. protocol
  166. ^ (self basicAt: 'protocol') ifNil: [ self defaultProtocol ]
  167. !
  168. protocol: aString
  169. | oldProtocol |
  170. oldProtocol := self protocol.
  171. self basicAt: 'protocol' put: aString.
  172. SystemAnnouncer current announce: (MethodMoved new
  173. method: self;
  174. oldProtocol: oldProtocol;
  175. yourself).
  176. self methodClass ifNotNil: [ :methodClass |
  177. methodClass organization addElement: aString.
  178. methodClass removeProtocolIfEmpty: oldProtocol ]
  179. !
  180. referencedClasses
  181. ^ self basicAt: 'referencedClasses'
  182. !
  183. selector
  184. ^ self basicAt: 'selector'
  185. !
  186. selector: aString
  187. self basicAt: 'selector' put: aString
  188. !
  189. source
  190. ^ (self basicAt: 'source') ifNil: [ '' ]
  191. !
  192. source: aString
  193. self basicAt: 'source' put: aString
  194. ! !
  195. !CompiledMethod methodsFor: 'defaults'!
  196. defaultProtocol
  197. ^ 'as yet unclassified'
  198. ! !
  199. !CompiledMethod methodsFor: 'evaluating'!
  200. sendTo: anObject arguments: aCollection
  201. ^ self fn applyTo: anObject arguments: aCollection
  202. ! !
  203. !CompiledMethod methodsFor: 'testing'!
  204. isCompiledMethod
  205. ^ true
  206. !
  207. isOverridden
  208. | selector |
  209. selector := self selector.
  210. self methodClass allSubclassesDo: [ :each |
  211. (each includesSelector: selector)
  212. ifTrue: [ ^ true ] ].
  213. ^ false
  214. !
  215. isOverride
  216. | superclass |
  217. superclass := self methodClass superclass.
  218. superclass ifNil: [ ^ false ].
  219. ^ (self methodClass superclass lookupSelector: self selector) notNil
  220. ! !
  221. Object subclass: #ForkPool
  222. instanceVariableNames: 'poolSize maxPoolSize queue worker'
  223. package: 'Kernel-Methods'!
  224. !ForkPool commentStamp!
  225. I am responsible for handling forked blocks.
  226. The pool size sets the maximum concurrent forked blocks.
  227. ## API
  228. The default instance is accessed with `#default`.
  229. The maximum concurrent forked blocks can be set with `#maxPoolSize:`.
  230. Forking is done via `BlockClosure >> #fork`!
  231. !ForkPool methodsFor: 'accessing'!
  232. maxPoolSize
  233. ^ maxPoolSize ifNil: [ self defaultMaxPoolSize ]
  234. !
  235. maxPoolSize: anInteger
  236. maxPoolSize := anInteger
  237. ! !
  238. !ForkPool methodsFor: 'actions'!
  239. fork: aBlock
  240. poolSize < self maxPoolSize ifTrue: [ self addWorker ].
  241. queue nextPut: aBlock
  242. ! !
  243. !ForkPool methodsFor: 'defaults'!
  244. defaultMaxPoolSize
  245. ^ self class defaultMaxPoolSize
  246. ! !
  247. !ForkPool methodsFor: 'initialization'!
  248. initialize
  249. super initialize.
  250. poolSize := 0.
  251. queue := Queue new.
  252. worker := self makeWorker
  253. !
  254. makeWorker
  255. | sentinel |
  256. sentinel := Object new.
  257. ^ [ | block |
  258. poolSize := poolSize - 1.
  259. block := queue nextIfAbsent: [ sentinel ].
  260. block == sentinel ifFalse: [
  261. [ block value ] ensure: [ self addWorker ] ]]
  262. ! !
  263. !ForkPool methodsFor: 'private'!
  264. addWorker
  265. worker valueWithTimeout: 0.
  266. poolSize := poolSize + 1
  267. ! !
  268. ForkPool class instanceVariableNames: 'default'!
  269. !ForkPool class methodsFor: 'accessing'!
  270. default
  271. ^ default ifNil: [ default := self new ]
  272. !
  273. defaultMaxPoolSize
  274. ^ 100
  275. !
  276. resetDefault
  277. default := nil
  278. ! !
  279. Object subclass: #Message
  280. instanceVariableNames: 'selector arguments'
  281. package: 'Kernel-Methods'!
  282. !Message commentStamp!
  283. In general, the system does not use instances of me for efficiency reasons.
  284. However, when a message is not understood by its receiver, the interpreter will make up an instance of it in order to capture the information involved in an actual message transmission.
  285. This instance is sent it as an argument with the message `#doesNotUnderstand:` to the receiver.
  286. See boot.js, `messageNotUnderstood` and its counterpart `Object >> #doesNotUnderstand:`
  287. ## API
  288. Besides accessing methods, `#sendTo:` provides a convenient way to send a message to an object.!
  289. !Message methodsFor: 'accessing'!
  290. arguments
  291. ^ arguments
  292. !
  293. arguments: anArray
  294. arguments := anArray
  295. !
  296. selector
  297. ^ selector
  298. !
  299. selector: aString
  300. selector := aString
  301. ! !
  302. !Message methodsFor: 'actions'!
  303. sendTo: anObject
  304. ^ anObject perform: self selector withArguments: self arguments
  305. ! !
  306. !Message methodsFor: 'printing'!
  307. printOn: aStream
  308. super printOn: aStream.
  309. aStream
  310. nextPutAll: '(';
  311. nextPutAll: self selector;
  312. nextPutAll: ')'
  313. ! !
  314. !Message class methodsFor: 'instance creation'!
  315. selector: aString arguments: anArray
  316. ^ self new
  317. selector: aString;
  318. arguments: anArray;
  319. yourself
  320. ! !
  321. Object subclass: #MessageSend
  322. instanceVariableNames: 'receiver message'
  323. package: 'Kernel-Methods'!
  324. !MessageSend commentStamp!
  325. I encapsulate message sends to objects. Arguments can be either predefined or supplied when the message send is performed.
  326. ## API
  327. Use `#value` to perform a message send with its predefined arguments and `#value:*` if additonal arguments have to supplied.!
  328. !MessageSend methodsFor: 'accessing'!
  329. arguments
  330. ^ message arguments
  331. !
  332. arguments: aCollection
  333. message arguments: aCollection
  334. !
  335. receiver
  336. ^ receiver
  337. !
  338. receiver: anObject
  339. receiver := anObject
  340. !
  341. selector
  342. ^ message selector
  343. !
  344. selector: aString
  345. message selector: aString
  346. ! !
  347. !MessageSend methodsFor: 'evaluating'!
  348. value
  349. ^ message sendTo: self receiver
  350. !
  351. value: anObject
  352. ^ message
  353. arguments: { anObject };
  354. sendTo: self receiver
  355. !
  356. value: firstArgument value: secondArgument
  357. ^ message
  358. arguments: { firstArgument. secondArgument };
  359. sendTo: self receiver
  360. !
  361. value: firstArgument value: secondArgument value: thirdArgument
  362. ^ message
  363. arguments: { firstArgument. secondArgument. thirdArgument };
  364. sendTo: self receiver
  365. !
  366. valueWithPossibleArguments: aCollection
  367. self arguments: aCollection.
  368. ^ self value
  369. ! !
  370. !MessageSend methodsFor: 'initialization'!
  371. initialize
  372. super initialize.
  373. message := Message new
  374. ! !
  375. !MessageSend methodsFor: 'printing'!
  376. printOn: aStream
  377. super printOn: aStream.
  378. aStream
  379. nextPutAll: '(';
  380. nextPutAll: self receiver;
  381. nextPutAll: ' >> ';
  382. nextPutAll: self selector;
  383. nextPutAll: ')'
  384. ! !
  385. Object subclass: #MethodContext
  386. instanceVariableNames: ''
  387. package: 'Kernel-Methods'!
  388. !MethodContext commentStamp!
  389. I hold all the dynamic state associated with the execution of either a method activation resulting from a message send. I am used to build the call stack while debugging.
  390. My instances are JavaScript `SmalltalkMethodContext` objects defined in `boot.js`.!
  391. !MethodContext methodsFor: 'accessing'!
  392. evaluatedSelector
  393. <return self.evaluatedSelector>
  394. !
  395. home
  396. <return self.homeContext>
  397. !
  398. index
  399. <return self.index || 0>
  400. !
  401. locals
  402. <return self.locals || {}>
  403. !
  404. method
  405. ^ self methodContext ifNotNil: [
  406. self methodContext receiver class lookupSelector: self methodContext selector ]
  407. !
  408. methodContext
  409. self isBlockContext ifFalse: [ ^ self ].
  410. ^ self outerContext ifNotNil: [ :outer |
  411. outer methodContext ]
  412. !
  413. outerContext
  414. <return self.outerContext || self.homeContext>
  415. !
  416. receiver
  417. <return self.receiver>
  418. !
  419. selector
  420. <
  421. if(self.selector) {
  422. return smalltalk.convertSelector(self.selector);
  423. } else {
  424. return nil;
  425. }
  426. >
  427. !
  428. sendIndexAt: aSelector
  429. <return self.sendIdx[aSelector] || 0>
  430. !
  431. sendIndexes
  432. <return self.sendIdx>
  433. !
  434. temps
  435. self deprecatedAPI.
  436. ^ self locals
  437. ! !
  438. !MethodContext methodsFor: 'converting'!
  439. asString
  440. ^ self isBlockContext
  441. ifTrue: [ 'a block (in ', self methodContext asString, ')' ]
  442. ifFalse: [ self receiver class name, ' >> ', self selector ]
  443. ! !
  444. !MethodContext methodsFor: 'printing'!
  445. printOn: aStream
  446. super printOn: aStream.
  447. aStream
  448. nextPutAll: '(';
  449. nextPutAll: self asString;
  450. nextPutAll: ')'
  451. ! !
  452. !MethodContext methodsFor: 'testing'!
  453. isBlockContext
  454. "Block context do not have selectors."
  455. ^ self selector isNil
  456. ! !
  457. Object subclass: #NativeFunction
  458. instanceVariableNames: ''
  459. package: 'Kernel-Methods'!
  460. !NativeFunction commentStamp!
  461. I am a wrapper around native functions, such as `WebSocket`.
  462. For 'normal' functions (whose constructor is the JavaScript `Function` object), use `BlockClosure`.
  463. ## API
  464. See the class-side `instance creation` methods for instance creation.
  465. Created instances will most probably be instance of `JSObjectProxy`.
  466. ## Usage example:
  467. | ws |
  468. ws := NativeFunction constructor: 'WebSocket' value: 'ws://localhost'.
  469. ws at: 'onopen' put: [ ws send: 'hey there from Amber' ]!
  470. !NativeFunction class methodsFor: 'instance creation'!
  471. constructor: aString
  472. <
  473. var native=eval(aString);
  474. return new native();
  475. >
  476. !
  477. constructor: aString value:anObject
  478. <
  479. var native=eval(aString);
  480. return new native(anObject);
  481. >
  482. !
  483. constructor: aString value:anObject value: anObject2
  484. <
  485. var native=eval(aString);
  486. return new native(anObject,anObject2);
  487. >
  488. !
  489. constructor: aString value:anObject value: anObject2 value:anObject3
  490. <
  491. var native=eval(aString);
  492. return new native(anObject,anObject2, anObject3);
  493. >
  494. ! !
  495. !NativeFunction class methodsFor: 'testing'!
  496. exists: aString
  497. ^ PlatformInterface existsGlobal: aString
  498. ! !
  499. Object subclass: #Timeout
  500. instanceVariableNames: 'rawTimeout'
  501. package: 'Kernel-Methods'!
  502. !Timeout commentStamp!
  503. I am wrapping the returns from `set{Timeout,Interval}`.
  504. ## Motivation
  505. Number suffices in browsers, but node.js returns an object.!
  506. !Timeout methodsFor: 'accessing'!
  507. rawTimeout: anObject
  508. rawTimeout := anObject
  509. ! !
  510. !Timeout methodsFor: 'timeout/interval'!
  511. clearInterval
  512. <
  513. var interval = self["@rawTimeout"];
  514. clearInterval(interval);
  515. >
  516. !
  517. clearTimeout
  518. <
  519. var timeout = self["@rawTimeout"];
  520. clearTimeout(timeout);
  521. >
  522. ! !
  523. !Timeout class methodsFor: 'instance creation'!
  524. on: anObject
  525. ^ self new rawTimeout: anObject; yourself
  526. ! !