Kernel-Methods.st 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965
  1. Smalltalk createPackage: 'Kernel-Methods'!
  2. Object subclass: #BlockClosure
  3. instanceVariableNames: 'prototype'
  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. <inlineJS: 'return self.toString()'>
  21. !
  22. numArgs
  23. <inlineJS: 'return self.length'>
  24. !
  25. prototype
  26. ^ prototype
  27. !
  28. receiver
  29. ^ nil
  30. ! !
  31. !BlockClosure methodsFor: 'controlling'!
  32. whileFalse
  33. self whileFalse: []
  34. !
  35. whileFalse: aBlock
  36. <inlineJS: 'while(!!$core.assert($self._value())) {aBlock._value()}'>
  37. !
  38. whileTrue
  39. self whileTrue: []
  40. !
  41. whileTrue: aBlock
  42. <inlineJS: 'while($core.assert($self._value())) {aBlock._value()}'>
  43. ! !
  44. !BlockClosure methodsFor: 'converting'!
  45. asCompiledMethod: aString
  46. <inlineJS: 'return $core.method({selector:aString, fn:self});'>
  47. !
  48. currySelf
  49. "Transforms [ :selfarg :x :y | stcode ] block
  50. which represents JS function (selfarg, x, y, ...) {jscode}
  51. into function (x, y, ...) {jscode} that takes selfarg from 'this'.
  52. IOW, it is usable as JS method and first arg takes the receiver."
  53. <inlineJS: '
  54. return function () {
  55. var args = [ this ];
  56. args.push.apply(args, arguments);
  57. return self.apply(null, args);
  58. }
  59. '>
  60. !
  61. provided
  62. "Returns JS proxy that allows to access 'static API', as in
  63. require provided resolve: ...
  64. or
  65. XMLHttpRequest provided DONE"
  66. ^ JSObjectProxy on: self
  67. ! !
  68. !BlockClosure methodsFor: 'error handling'!
  69. on: anErrorClass do: aBlock
  70. "All exceptions thrown in the Smalltalk stack are cought.
  71. Convert all JS exceptions to JavaScriptException instances."
  72. ^ self tryCatch: [ :error | | smalltalkError |
  73. smalltalkError := Smalltalk asSmalltalkException: error.
  74. (smalltalkError isKindOf: anErrorClass)
  75. ifTrue: [ aBlock value: smalltalkError ]
  76. ifFalse: [ smalltalkError pass ] ]
  77. !
  78. tryCatch: aBlock
  79. <inlineJS: '
  80. try {
  81. return $self._value();
  82. } catch(error) {
  83. // pass non-local returns undetected
  84. if (Array.isArray(error) && error.length === 1) throw error;
  85. return aBlock._value_(error);
  86. }
  87. '>
  88. ! !
  89. !BlockClosure methodsFor: 'evaluating'!
  90. applyTo: anObject arguments: aCollection
  91. <inlineJS: 'return self.apply(anObject, aCollection)'>
  92. !
  93. ensure: aBlock
  94. <inlineJS: 'try{return $self._value()}finally{aBlock._value()}'>
  95. !
  96. new
  97. "Use the receiver as a JS constructor.
  98. *Do not* use this method to instanciate Smalltalk objects!!"
  99. <inlineJS: 'return new self()'>
  100. !
  101. newValue: anObject
  102. ^ self newWithValues: { anObject }
  103. !
  104. newValue: anObject value: anObject2
  105. ^ self newWithValues: { anObject. anObject2 }.
  106. !
  107. newValue: anObject value: anObject2 value: anObject3
  108. ^ self newWithValues: { anObject. anObject2. anObject3 }.
  109. !
  110. newWithValues: aCollection
  111. "Simulates JS new operator by combination of Object.create and .apply"
  112. <inlineJS: '
  113. var object = Object.create(self.prototype);
  114. var result = self.apply(object, aCollection);
  115. return typeof result === "object" ? result : object;
  116. '>
  117. !
  118. timeToRun
  119. "Answer the number of milliseconds taken to execute this block."
  120. ^ Date millisecondsToRun: self
  121. !
  122. value
  123. <inlineJS: 'return self();'>
  124. !
  125. value: anArg
  126. <inlineJS: 'return self(anArg);'>
  127. !
  128. value: firstArg value: secondArg
  129. <inlineJS: 'return self(firstArg, secondArg);'>
  130. !
  131. value: firstArg value: secondArg value: thirdArg
  132. <inlineJS: 'return self(firstArg, secondArg, thirdArg);'>
  133. !
  134. valueWithPossibleArguments: aCollection
  135. <inlineJS: 'return self.apply(null, aCollection);'>
  136. ! !
  137. !BlockClosure methodsFor: 'timeout/interval'!
  138. fork
  139. ForkPool default fork: self
  140. !
  141. valueWithInterval: aNumber
  142. <inlineJS: '
  143. var interval = setInterval(self, aNumber);
  144. return $globals.Timeout._on_(interval);
  145. '>
  146. !
  147. valueWithTimeout: aNumber
  148. <inlineJS: '
  149. var timeout = setTimeout(self, aNumber);
  150. return $globals.Timeout._on_(timeout);
  151. '>
  152. ! !
  153. Object subclass: #CompiledMethod
  154. instanceVariableNames: ''
  155. package: 'Kernel-Methods'!
  156. !CompiledMethod commentStamp!
  157. I represent a class method of the system. I hold the source and compiled code of a class method.
  158. ## API
  159. My instances can be accessed using `Behavior >> #methodAt:`
  160. Object methodAt: 'asString'
  161. Source code access:
  162. (String methodAt: 'lines') source
  163. Referenced classes:
  164. (String methodAt: 'lines') referencedClasses
  165. Messages sent from an instance:
  166. (String methodAt: 'lines') messageSends!
  167. !CompiledMethod methodsFor: 'accessing'!
  168. arguments
  169. <inlineJS: 'return self.args || []'>
  170. !
  171. category
  172. ^ self protocol
  173. !
  174. fn
  175. ^ self basicAt: 'fn'
  176. !
  177. fn: aBlock
  178. self basicAt: 'fn' put: aBlock
  179. !
  180. messageSends
  181. ^ self basicAt: 'messageSends'
  182. !
  183. methodClass
  184. ^ self basicAt: 'owner'
  185. !
  186. package
  187. "Answer the package the receiver belongs to:
  188. - if it is an extension method, answer the corresponding package
  189. - else answer the `methodClass` package"
  190. ^ self methodClass ifNotNil: [ :class | class packageOfProtocol: self protocol ]
  191. !
  192. protocol
  193. ^ (self basicAt: 'protocol') ifNil: [ self defaultProtocol ]
  194. !
  195. protocol: aString
  196. | oldProtocol |
  197. oldProtocol := self protocol.
  198. self basicAt: 'protocol' put: aString.
  199. SystemAnnouncer current announce: (MethodMoved new
  200. method: self;
  201. oldProtocol: oldProtocol;
  202. yourself).
  203. self methodClass ifNotNil: [ :methodClass |
  204. methodClass organization addElement: aString.
  205. methodClass removeProtocolIfEmpty: oldProtocol ]
  206. !
  207. referencedClasses
  208. ^ self basicAt: 'referencedClasses'
  209. !
  210. selector
  211. ^ self basicAt: 'selector'
  212. !
  213. selector: aString
  214. self basicAt: 'selector' put: aString
  215. !
  216. source
  217. ^ (self basicAt: 'source') ifNil: [ '' ]
  218. !
  219. source: aString
  220. self basicAt: 'source' put: aString
  221. ! !
  222. !CompiledMethod methodsFor: 'browsing'!
  223. browse
  224. Finder findMethod: self
  225. ! !
  226. !CompiledMethod methodsFor: 'defaults'!
  227. defaultProtocol
  228. ^ 'as yet unclassified'
  229. ! !
  230. !CompiledMethod methodsFor: 'evaluating'!
  231. sendTo: anObject arguments: aCollection
  232. ^ self fn applyTo: anObject arguments: aCollection
  233. ! !
  234. !CompiledMethod methodsFor: 'testing'!
  235. isCompiledMethod
  236. ^ true
  237. !
  238. isOverridden
  239. | selector |
  240. selector := self selector.
  241. self methodClass allSubclassesDo: [ :each |
  242. (each includesSelector: selector)
  243. ifTrue: [ ^ true ] ].
  244. ^ false
  245. !
  246. isOverride
  247. | superclass |
  248. superclass := self methodClass superclass.
  249. superclass ifNil: [ ^ false ].
  250. ^ (self methodClass superclass lookupSelector: self selector) notNil
  251. ! !
  252. Object subclass: #ForkPool
  253. instanceVariableNames: 'poolSize maxPoolSize queue worker'
  254. package: 'Kernel-Methods'!
  255. !ForkPool commentStamp!
  256. I am responsible for handling forked blocks.
  257. The pool size sets the maximum concurrent forked blocks.
  258. ## API
  259. The default instance is accessed with `#default`.
  260. The maximum concurrent forked blocks can be set with `#maxPoolSize:`.
  261. Forking is done via `BlockClosure >> #fork`!
  262. !ForkPool methodsFor: 'accessing'!
  263. maxPoolSize
  264. ^ maxPoolSize ifNil: [ self defaultMaxPoolSize ]
  265. !
  266. maxPoolSize: anInteger
  267. maxPoolSize := anInteger
  268. ! !
  269. !ForkPool methodsFor: 'actions'!
  270. fork: aBlock
  271. poolSize < self maxPoolSize ifTrue: [ self addWorker ].
  272. queue nextPut: aBlock
  273. ! !
  274. !ForkPool methodsFor: 'defaults'!
  275. defaultMaxPoolSize
  276. ^ self class defaultMaxPoolSize
  277. ! !
  278. !ForkPool methodsFor: 'initialization'!
  279. initialize
  280. super initialize.
  281. poolSize := 0.
  282. queue := Queue new.
  283. worker := self makeWorker
  284. !
  285. makeWorker
  286. | sentinel |
  287. sentinel := Object new.
  288. ^ [ | block |
  289. poolSize := poolSize - 1.
  290. block := queue nextIfAbsent: [ sentinel ].
  291. block == sentinel ifFalse: [
  292. [ block value ] ensure: [ self addWorker ] ]]
  293. ! !
  294. !ForkPool methodsFor: 'private'!
  295. addWorker
  296. worker valueWithTimeout: 0.
  297. poolSize := poolSize + 1
  298. ! !
  299. ForkPool class instanceVariableNames: 'default'!
  300. !ForkPool class methodsFor: 'accessing'!
  301. default
  302. ^ default ifNil: [ default := self new ]
  303. !
  304. defaultMaxPoolSize
  305. ^ 100
  306. !
  307. resetDefault
  308. default := nil
  309. ! !
  310. Object subclass: #Message
  311. instanceVariableNames: 'selector arguments'
  312. package: 'Kernel-Methods'!
  313. !Message commentStamp!
  314. In general, the system does not use instances of me for efficiency reasons.
  315. 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.
  316. This instance is sent it as an argument with the message `#doesNotUnderstand:` to the receiver.
  317. See boot.js, `messageNotUnderstood` and its counterpart `Object >> #doesNotUnderstand:`
  318. ## API
  319. Besides accessing methods, `#sendTo:` provides a convenient way to send a message to an object.!
  320. !Message methodsFor: 'accessing'!
  321. arguments
  322. ^ arguments
  323. !
  324. arguments: anArray
  325. arguments := anArray
  326. !
  327. selector
  328. ^ selector
  329. !
  330. selector: aString
  331. selector := aString
  332. ! !
  333. !Message methodsFor: 'actions'!
  334. sendTo: anObject
  335. ^ anObject perform: self selector withArguments: self arguments
  336. ! !
  337. !Message methodsFor: 'printing'!
  338. printOn: aStream
  339. super printOn: aStream.
  340. aStream
  341. nextPutAll: '(';
  342. nextPutAll: self selector;
  343. nextPutAll: ')'
  344. ! !
  345. !Message class methodsFor: 'dnu handling'!
  346. selector: aString arguments: anArray notUnderstoodBy: anObject
  347. "Creates the message and passes it to #doesNotUnderstand:.
  348. Used by kernel to handle MNU."
  349. ^ anObject doesNotUnderstand:
  350. (self selector: aString arguments: anArray)
  351. ! !
  352. !Message class methodsFor: 'instance creation'!
  353. selector: aString arguments: anArray
  354. ^ self new
  355. selector: aString;
  356. arguments: anArray;
  357. yourself
  358. ! !
  359. Object subclass: #MessageSend
  360. instanceVariableNames: 'receiver message'
  361. package: 'Kernel-Methods'!
  362. !MessageSend commentStamp!
  363. I encapsulate message sends to objects. Arguments can be either predefined or supplied when the message send is performed.
  364. ## API
  365. Use `#value` to perform a message send with its predefined arguments and `#value:*` if additonal arguments have to supplied.!
  366. !MessageSend methodsFor: 'accessing'!
  367. arguments
  368. ^ message arguments
  369. !
  370. arguments: aCollection
  371. message arguments: aCollection
  372. !
  373. receiver
  374. ^ receiver
  375. !
  376. receiver: anObject
  377. receiver := anObject
  378. !
  379. selector
  380. ^ message selector
  381. !
  382. selector: aString
  383. message selector: aString
  384. ! !
  385. !MessageSend methodsFor: 'evaluating'!
  386. value
  387. ^ message sendTo: self receiver
  388. !
  389. value: anObject
  390. ^ message
  391. arguments: { anObject };
  392. sendTo: self receiver
  393. !
  394. value: firstArgument value: secondArgument
  395. ^ message
  396. arguments: { firstArgument. secondArgument };
  397. sendTo: self receiver
  398. !
  399. value: firstArgument value: secondArgument value: thirdArgument
  400. ^ message
  401. arguments: { firstArgument. secondArgument. thirdArgument };
  402. sendTo: self receiver
  403. !
  404. valueWithPossibleArguments: aCollection
  405. self arguments: aCollection.
  406. ^ self value
  407. ! !
  408. !MessageSend methodsFor: 'initialization'!
  409. initialize
  410. super initialize.
  411. message := Message new
  412. ! !
  413. !MessageSend methodsFor: 'printing'!
  414. printOn: aStream
  415. super printOn: aStream.
  416. aStream
  417. nextPutAll: '(';
  418. nextPutAll: self receiver;
  419. nextPutAll: ' >> ';
  420. nextPutAll: self selector;
  421. nextPutAll: ')'
  422. ! !
  423. Object subclass: #MethodContext
  424. instanceVariableNames: 'receiver evaluatedSelector homeContext index locals outerContext selector sendIdx supercall'
  425. package: 'Kernel-Methods'!
  426. !MethodContext commentStamp!
  427. 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.
  428. My instances are JavaScript `SmalltalkMethodContext` objects defined in `boot.js`.!
  429. !MethodContext methodsFor: 'accessing'!
  430. basicReceiver
  431. ^ receiver
  432. !
  433. evaluatedSelector
  434. ^ evaluatedSelector
  435. !
  436. home
  437. ^ homeContext
  438. !
  439. index
  440. ^ index ifNil: [ 0 ]
  441. !
  442. locals
  443. ^ locals
  444. !
  445. outerContext
  446. ^ outerContext ifNil: [ self home ]
  447. !
  448. selector
  449. ^ selector ifNotNil: [ Smalltalk core js2st: selector ]
  450. !
  451. sendIndexes
  452. ^ sendIdx
  453. !
  454. stubHere
  455. homeContext := JSObjectProxy undefined
  456. !
  457. supercall
  458. ^ supercall = true
  459. ! !
  460. !MethodContext methodsFor: 'error handling'!
  461. stubToAtMost: anInteger
  462. | context |
  463. context := self.
  464. anInteger timesRepeat: [ context := context ifNotNil: [ context home ] ].
  465. context ifNotNil: [ context stubHere ]
  466. ! !
  467. Object subclass: #NativeFunction
  468. instanceVariableNames: ''
  469. package: 'Kernel-Methods'!
  470. !NativeFunction commentStamp!
  471. I am a wrapper around native functions, such as `WebSocket`.
  472. For 'normal' functions (whose constructor is the JavaScript `Function` object), use `BlockClosure`.
  473. ## API
  474. See the class-side `instance creation` methods for instance creation.
  475. Created instances will most probably be instance of `JSObjectProxy`.
  476. ## Usage example:
  477. | ws |
  478. ws := NativeFunction constructor: 'WebSocket' value: 'ws://localhost'.
  479. ws at: 'onopen' put: [ ws send: 'hey there from Amber' ]!
  480. !NativeFunction class methodsFor: 'function calling'!
  481. functionNamed: aString
  482. <inlineJS: '
  483. var nativeFunc=$globals.Platform._globals[aString];
  484. return nativeFunc();
  485. '>
  486. !
  487. functionNamed: aString value: anObject
  488. <inlineJS: '
  489. var nativeFunc=$globals.Platform._globals()[aString];
  490. return nativeFunc(anObject);
  491. '>
  492. !
  493. functionNamed: aString value: anObject value: anObject2
  494. <inlineJS: '
  495. var nativeFunc=$globals.Platform._globals()[aString];
  496. return nativeFunc(anObject,anObject2);
  497. '>
  498. !
  499. functionNamed: aString value: anObject value: anObject2 value: anObject3
  500. <inlineJS: '
  501. var nativeFunc=$globals.Platform._globals()[aString];
  502. return nativeFunc(anObject,anObject2, anObject3);
  503. '>
  504. !
  505. functionNamed: aString valueWithArgs: args
  506. <inlineJS: '
  507. var nativeFunc=$globals.Platform._globals()[aString];
  508. return Function.prototype.apply.call(nativeFunc, null, args);
  509. '>
  510. !
  511. functionOf: nativeFunc
  512. <inlineJS: '
  513. return nativeFunc();
  514. '>
  515. !
  516. functionOf: nativeFunc value: anObject
  517. <inlineJS: '
  518. return nativeFunc(anObject);
  519. '>
  520. !
  521. functionOf: nativeFunc value: anObject value: anObject2
  522. <inlineJS: '
  523. return nativeFunc(anObject,anObject2);
  524. '>
  525. !
  526. functionOf: nativeFunc value: anObject value: anObject2 value: anObject3
  527. <inlineJS: '
  528. return nativeFunc(anObject,anObject2, anObject3);
  529. '>
  530. !
  531. functionOf: nativeFunc valueWithArgs: args
  532. <inlineJS: '
  533. return Function.prototype.apply.call(nativeFunc, null, args);
  534. '>
  535. ! !
  536. !NativeFunction class methodsFor: 'instance creation'!
  537. constructorNamed: aString
  538. <inlineJS: '
  539. var nativeFunc=$globals.Platform._globals()[aString];
  540. return new nativeFunc();
  541. '>
  542. !
  543. constructorNamed: aString value: anObject
  544. <inlineJS: '
  545. var nativeFunc=$globals.Platform._globals()[aString];
  546. return new nativeFunc(anObject);
  547. '>
  548. !
  549. constructorNamed: aString value: anObject value: anObject2
  550. <inlineJS: '
  551. var nativeFunc=$globals.Platform._globals[aString];
  552. return new nativeFunc(anObject,anObject2);
  553. '>
  554. !
  555. constructorNamed: aString value: anObject value: anObject2 value: anObject3
  556. <inlineJS: '
  557. var nativeFunc=$globals.Platform._globals[aString];
  558. return new nativeFunc(anObject,anObject2, anObject3);
  559. '>
  560. !
  561. constructorOf: nativeFunc
  562. <inlineJS: '
  563. return new nativeFunc();
  564. '>
  565. !
  566. constructorOf: nativeFunc value: anObject
  567. <inlineJS: '
  568. return new nativeFunc(anObject);
  569. '>
  570. !
  571. constructorOf: nativeFunc value: anObject value: anObject2
  572. <inlineJS: '
  573. return new nativeFunc(anObject,anObject2);
  574. '>
  575. !
  576. constructorOf: nativeFunc value: anObject value: anObject2 value: anObject3
  577. <inlineJS: '
  578. return new nativeFunc(anObject,anObject2, anObject3);
  579. '>
  580. ! !
  581. !NativeFunction class methodsFor: 'method calling'!
  582. methodOf: nativeFunc this: thisObject
  583. <inlineJS: '
  584. return Function.prototype.call.call(nativeFunc, thisObject);
  585. '>
  586. !
  587. methodOf: nativeFunc this: thisObject value: anObject
  588. <inlineJS: '
  589. return Function.prototype.call.call(nativeFunc, thisObject, anObject);
  590. '>
  591. !
  592. methodOf: nativeFunc this: thisObject value: anObject value: anObject2
  593. <inlineJS: '
  594. return Function.prototype.call.call(nativeFunc, thisObject,anObject,anObject2);
  595. '>
  596. !
  597. methodOf: nativeFunc this: thisObject value: anObject value: anObject2 value: anObject3
  598. <inlineJS: '
  599. return Function.prototype.call.call(nativeFunc, thisObject,anObject,anObject2, anObject3);
  600. '>
  601. !
  602. methodOf: nativeFunc this: thisObject valueWithArgs: args
  603. <inlineJS: '
  604. return Function.prototype.apply.call(nativeFunc, thisObject, args);
  605. '>
  606. ! !
  607. !NativeFunction class methodsFor: 'testing'!
  608. exists: aString
  609. ^ Platform includesGlobal: aString
  610. !
  611. isNativeFunction: anObject
  612. <inlineJS: 'return typeof anObject === "function"'>
  613. ! !
  614. Trait named: #TMethodContext
  615. package: 'Kernel-Methods'!
  616. !TMethodContext methodsFor: 'accessing'!
  617. basicReceiver
  618. self subclassResponsibility
  619. !
  620. findContextSuchThat: testBlock
  621. "Search self and my sender chain for first one that satisfies `testBlock`.
  622. Answer `nil` if none satisfy"
  623. | context |
  624. context := self.
  625. [ context isNil] whileFalse: [
  626. (testBlock value: context)
  627. ifTrue: [ ^ context ].
  628. context := context outerContext ].
  629. ^ nil
  630. !
  631. home
  632. self subclassResponsibility
  633. !
  634. index
  635. self subclassResponsibility
  636. !
  637. locals
  638. self subclassResponsibility
  639. !
  640. method
  641. | method lookupClass receiverClass supercall |
  642. self methodContext ifNil: [ ^ nil ].
  643. receiverClass := self methodContext receiver class.
  644. method := receiverClass lookupSelector: self methodContext selector.
  645. supercall := self outerContext
  646. ifNil: [ false ]
  647. ifNotNil: [ :outer | outer supercall ].
  648. ^ supercall
  649. ifFalse: [ method ]
  650. ifTrue: [ method methodClass superclass lookupSelector: self methodContext selector ]
  651. !
  652. methodContext
  653. self isBlockContext ifFalse: [ ^ self ].
  654. ^ self outerContext ifNotNil: [ :outer |
  655. outer methodContext ]
  656. !
  657. outerContext
  658. self subclassResponsibility
  659. !
  660. receiver
  661. ^ (self isBlockContext and: [ self outerContext notNil ])
  662. ifTrue: [ self outerContext receiver ]
  663. ifFalse: [ self basicReceiver ]
  664. !
  665. selector
  666. self subclassResponsibility
  667. !
  668. sendIndexes
  669. self subclassResponsibility
  670. !
  671. supercall
  672. self subclassResponsibility
  673. ! !
  674. !TMethodContext methodsFor: 'converting'!
  675. asString
  676. ^ self isBlockContext
  677. ifTrue: [ 'a block (in ', self methodContext asString, ')' ]
  678. ifFalse: [
  679. | methodClass |
  680. methodClass := self method methodClass.
  681. methodClass = self receiver class
  682. ifTrue: [ self receiver class name, ' >> ', self selector ]
  683. ifFalse: [ self receiver class name, '(', methodClass name, ') >> ', self selector ] ]
  684. ! !
  685. !TMethodContext methodsFor: 'printing'!
  686. printOn: aStream
  687. super printOn: aStream.
  688. aStream
  689. nextPutAll: '(';
  690. nextPutAll: self asString;
  691. nextPutAll: ')'
  692. ! !
  693. !TMethodContext methodsFor: 'testing'!
  694. isBlockContext
  695. "Block context do not have selectors."
  696. ^ self selector isNil
  697. ! !
  698. Object subclass: #Timeout
  699. instanceVariableNames: 'rawTimeout'
  700. package: 'Kernel-Methods'!
  701. !Timeout commentStamp!
  702. I am wrapping the returns from `set{Timeout,Interval}`.
  703. ## Motivation
  704. Number suffices in browsers, but node.js returns an object.!
  705. !Timeout methodsFor: 'accessing'!
  706. rawTimeout: anObject
  707. rawTimeout := anObject
  708. ! !
  709. !Timeout methodsFor: 'timeout/interval'!
  710. clearInterval
  711. <inlineJS: '
  712. var interval = $self.rawTimeout;
  713. clearInterval(interval);
  714. '>
  715. !
  716. clearTimeout
  717. <inlineJS: '
  718. var timeout = $self.rawTimeout;
  719. clearTimeout(timeout);
  720. '>
  721. ! !
  722. !Timeout class methodsFor: 'instance creation'!
  723. on: anObject
  724. ^ self new rawTimeout: anObject; yourself
  725. ! !
  726. MethodContext setTraitComposition: {TMethodContext} asTraitComposition!
  727. ! !