| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715 | 
							- Smalltalk current createPackage: 'Kernel-Methods'!
 
- Object subclass: #BlockClosure
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Methods'!
 
- !BlockClosure commentStamp!
 
- I represent a lexical closure.
 
- I am is directly mapped to JavaScript Function.
 
- ## API
 
- 1. Evaluation
 
-     My instances get evaluated with the `#value*` methods in the 'evaluating' protocol.
 
-     Example: ` [ :x | x + 1 ] value: 3 "Answers 4" `
 
- 2. Control structures
 
-     Blocks are used (together with `Boolean`) for control structures (methods in the `controlling` protocol).
 
-     Example: `aBlock whileTrue: [ ... ]`
 
- 3. Error handling
 
-     I provide the `#on:do:` method for handling exceptions.
 
-     Example: ` aBlock on: MessageNotUnderstood do: [ :ex | ... ] `!
 
- !BlockClosure methodsFor: 'accessing'!
 
- compiledSource
 
- 	<return self.toString()>
 
- !
 
- numArgs
 
- 	<return self.length>
 
- !
 
- receiver
 
- 	^ nil
 
- ! !
 
- !BlockClosure methodsFor: 'controlling'!
 
- whileFalse
 
- 	self whileFalse: []
 
- !
 
- whileFalse: aBlock
 
- 	<while(!!smalltalk.assert(self._value())) {aBlock._value()}>
 
- !
 
- whileTrue
 
- 	self whileTrue: []
 
- !
 
- whileTrue: aBlock
 
- 	<while(smalltalk.assert(self._value())) {aBlock._value()}>
 
- ! !
 
- !BlockClosure methodsFor: 'converting'!
 
- asCompiledMethod: aString
 
- 	<return smalltalk.method({selector:aString, fn:self});>
 
- !
 
- currySelf
 
- 	"Transforms [ :selfarg :x :y | stcode ] block
 
- 	which represents JS function (selfarg, x, y, ...) {jscode}
 
- 	into function (x, y, ...) {jscode} that takes selfarg from 'this'.
 
- 	IOW, it is usable as JS method and first arg takes the receiver."
 
- 	
 
- 	<
 
- 		return function () {
 
- 			var args = [ this ];
 
- 			args.push.apply(args, arguments);
 
- 			return self.apply(null, args);
 
- 		}
 
- 	>
 
- ! !
 
- !BlockClosure methodsFor: 'error handling'!
 
- on: anErrorClass do: aBlock
 
- 	"All exceptions thrown in the Smalltalk stack are cought.
 
- 	Convert all JS exceptions to JavaScriptException instances."
 
- 	
 
- 	^self try: self catch: [ :error | | smalltalkError |
 
- 		smalltalkError := Smalltalk current asSmalltalkException: error.
 
- 		(smalltalkError isKindOf: anErrorClass)
 
- 		ifTrue: [ aBlock value: smalltalkError ]
 
- 		ifFalse: [ smalltalkError resignal ] ]
 
- ! !
 
- !BlockClosure methodsFor: 'evaluating'!
 
- applyTo: anObject arguments: aCollection
 
- 	<return self.apply(anObject, aCollection)>
 
- !
 
- ensure: aBlock
 
- 	<try{return self._value()}finally{aBlock._value()}>
 
- !
 
- new
 
- 	"Use the receiver as a JS constructor.
 
- 	*Do not* use this method to instanciate Smalltalk objects!!"
 
- 	<return new self()>
 
- !
 
- newValue: anObject
 
- ^ self newWithValues: { anObject }
 
- !
 
- newValue: anObject value: anObject2
 
- ^ self newWithValues: { anObject. anObject2 }.
 
- !
 
- newValue: anObject value: anObject2 value: anObject3
 
- ^ self newWithValues: { anObject. anObject2. anObject3 }.
 
- !
 
- newWithValues: aCollection
 
- "Use the receiver as a JavaScript constructor with a variable number of arguments.
 
- Answer the object created using the operator `new`.
 
- This algorithm was inspired by http://stackoverflow.com/a/6069331.
 
- Here's a general breakdown of what's going on:
 
- 1) Create a new, empty constructor function.
 
- 2) Set it's prototype to the receiver's prototype. Because the receiver is a `BlockClosure`, it is also a JavaScript function.
 
- 3) Instantiate a new object using the constructor function just created. 
 
-    This forces the interpreter to set the internal [[prototype]] property to what was set on the function before. 
 
-    This has to be done, as we have no access to the [[prototype]] property externally.
 
- 4) Apply `self` to the object I just instantiated."
 
- <
 
- 	var constructor = function() {};
 
- 	constructor.prototype = self.prototype;
 
- 	var object = new constructor;
 
- 	var result = self.apply(object, aCollection);
 
- 	return typeof result === "object" ? result : object;
 
- >
 
- !
 
- timeToRun
 
- 	"Answer the number of milliseconds taken to execute this block."
 
- 	^ Date millisecondsToRun: self
 
- !
 
- value
 
- 	<return self();>
 
- !
 
- value: anArg
 
- 	<return self(anArg);>
 
- !
 
- value: firstArg value: secondArg
 
- 	<return self(firstArg, secondArg);>
 
- !
 
- value: firstArg value: secondArg value: thirdArg
 
- 	<return self(firstArg, secondArg, thirdArg);>
 
- !
 
- valueWithPossibleArguments: aCollection
 
- 	<return self.apply(null, aCollection);>
 
- ! !
 
- !BlockClosure methodsFor: 'timeout/interval'!
 
- fork
 
- 	ForkPool default fork: self
 
- !
 
- valueWithInterval: aNumber
 
- 	<
 
- 		var interval = setInterval(self, aNumber);
 
- 		return smalltalk.Timeout._on_(interval);
 
- 	>
 
- !
 
- valueWithTimeout: aNumber
 
- 	<
 
- 		var timeout = setTimeout(self, aNumber);
 
- 		return smalltalk.Timeout._on_(timeout);
 
- 	>
 
- ! !
 
- Object subclass: #CompiledMethod
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Methods'!
 
- !CompiledMethod commentStamp!
 
- I represent a class method of the system. I hold the source and compiled code of a class method.
 
- ## API
 
- My instances can be accessed using `Behavior >> #methodAt:`
 
-     Object methodAt: 'asString'
 
- Source code access:
 
- 	(String methodAt: 'lines') source
 
- Referenced classes:
 
- 	(String methodAt: 'lines') referencedClasses
 
- Messages sent from an instance:
 
- 	
 
- 	(String methodAt: 'lines') messageSends!
 
- !CompiledMethod methodsFor: 'accessing'!
 
- arguments
 
- 	<return self.args || []>
 
- !
 
- category
 
- 	^(self basicAt: 'category') ifNil: [ self defaultCategory ]
 
- !
 
- category: aString
 
- 	| oldProtocol |
 
- 	oldProtocol := self protocol.
 
- 	self basicAt: 'category' put: aString.
 
- 	SystemAnnouncer current announce: (MethodMoved new
 
- 		method: self;
 
- 		oldProtocol: oldProtocol;
 
- 		yourself).
 
- 	self methodClass ifNotNil: [
 
- 		self methodClass organization addElement: aString.
 
- 	
 
- 		(self methodClass methods
 
- 			select: [ :each | each protocol = oldProtocol ])
 
- 			ifEmpty: [ self methodClass organization removeElement: oldProtocol ] ]
 
- !
 
- fn
 
- 	^self basicAt: 'fn'
 
- !
 
- fn: aBlock
 
- 	self basicAt: 'fn' put: aBlock
 
- !
 
- messageSends
 
- 	^self basicAt: 'messageSends'
 
- !
 
- methodClass
 
- 	^self basicAt: 'methodClass'
 
- !
 
- protocol
 
- 	^ self category
 
- !
 
- protocol: aString
 
- 	self category: aString
 
- !
 
- referencedClasses
 
- 	^self basicAt: 'referencedClasses'
 
- !
 
- selector
 
- 	^self basicAt: 'selector'
 
- !
 
- selector: aString
 
- 	self basicAt: 'selector' put: aString
 
- !
 
- source
 
- 	^(self basicAt: 'source') ifNil: ['']
 
- !
 
- source: aString
 
- 	self basicAt: 'source' put: aString
 
- ! !
 
- !CompiledMethod methodsFor: 'defaults'!
 
- defaultCategory
 
- 	^ 'as yet unclassified'
 
- ! !
 
- !CompiledMethod methodsFor: 'testing'!
 
- isCompiledMethod
 
- 	^ true
 
- !
 
- isOverridden
 
- 	| selector |
 
-     
 
-     selector := self selector.
 
-     self methodClass allSubclassesDo: [ :each |
 
- 	    (each includesSelector: selector)
 
-         	ifTrue: [ ^ true ] ].
 
- 	^ false
 
- !
 
- isOverride
 
- 	| superclass |
 
-     
 
-     superclass := self methodClass superclass.
 
- 	superclass ifNil: [ ^ false ].
 
- 	
 
-     ^ (self methodClass superclass lookupSelector: self selector) notNil
 
- ! !
 
- Object subclass: #ForkPool
 
- 	instanceVariableNames: 'poolSize maxPoolSize queue worker'
 
- 	package: 'Kernel-Methods'!
 
- !ForkPool commentStamp!
 
- I am responsible for handling forked blocks.
 
- The pool size sets the maximum concurrent forked blocks.
 
- ## API
 
- The default instance is accessed with `#default`.
 
- The maximum concurrent forked blocks can be set with `#maxPoolSize:`.
 
- Forking is done via `BlockClosure >> #fork`!
 
- !ForkPool methodsFor: 'accessing'!
 
- maxPoolSize
 
- 	^ maxPoolSize ifNil: [ self defaultMaxPoolSize ]
 
- !
 
- maxPoolSize: anInteger
 
- 	maxPoolSize := anInteger
 
- ! !
 
- !ForkPool methodsFor: 'actions'!
 
- fork: aBlock
 
- 	poolSize < self maxPoolSize ifTrue: [ self addWorker ].
 
- 	queue nextPut: aBlock
 
- ! !
 
- !ForkPool methodsFor: 'defaults'!
 
- defaultMaxPoolSize
 
- 	^ self class defaultMaxPoolSize
 
- ! !
 
- !ForkPool methodsFor: 'initialization'!
 
- initialize
 
- 	super initialize.
 
- 	
 
- 	poolSize := 0.
 
- 	queue := Queue new.
 
- 	worker := self makeWorker
 
- !
 
- makeWorker
 
- 	| sentinel |
 
- 	sentinel := Object new.
 
- 	^[ | block |
 
- 		poolSize := poolSize - 1.
 
- 		block := queue nextIfAbsent: [ sentinel ].
 
- 		block == sentinel ifFalse: [
 
- 			[ block value ] ensure: [ self addWorker ]]]
 
- ! !
 
- !ForkPool methodsFor: 'private'!
 
- addWorker
 
- 	worker valueWithTimeout: 0.
 
- 	poolSize := poolSize + 1
 
- ! !
 
- ForkPool class instanceVariableNames: 'default'!
 
- !ForkPool class methodsFor: 'accessing'!
 
- default
 
- 	^default ifNil: [ default := self new ]
 
- !
 
- defaultMaxPoolSize
 
- 	^100
 
- !
 
- resetDefault
 
- 	default := nil
 
- ! !
 
- Object subclass: #Message
 
- 	instanceVariableNames: 'selector arguments'
 
- 	package: 'Kernel-Methods'!
 
- !Message commentStamp!
 
- In general, the system does not use instances of me for efficiency reasons.
 
- 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.
 
- This instance is sent it as an argument with the message `#doesNotUnderstand:` to the receiver.
 
- See boot.js, `messageNotUnderstood` and its counterpart `Object >> #doesNotUnderstand:`
 
- ## API
 
- Besides accessing methods, `#sendTo:` provides a convenient way to send a message to an object.!
 
- !Message methodsFor: 'accessing'!
 
- arguments
 
- 	^arguments
 
- !
 
- arguments: anArray
 
- 	arguments := anArray
 
- !
 
- selector
 
- 	^selector
 
- !
 
- selector: aString
 
- 	selector := aString
 
- ! !
 
- !Message methodsFor: 'actions'!
 
- sendTo: anObject
 
- 	^ anObject perform: self selector withArguments: self arguments
 
- ! !
 
- !Message methodsFor: 'printing'!
 
- printOn: aStream
 
- 	super printOn: aStream.
 
- 	aStream
 
- 		nextPutAll: '(';
 
- 		nextPutAll: self selector;
 
- 		nextPutAll: ')'
 
- ! !
 
- !Message class methodsFor: 'instance creation'!
 
- selector: aString arguments: anArray
 
- 	^self new
 
- 		selector: aString;
 
- 		arguments: anArray;
 
- 		yourself
 
- ! !
 
- Object subclass: #MessageSend
 
- 	instanceVariableNames: 'receiver message'
 
- 	package: 'Kernel-Methods'!
 
- !MessageSend commentStamp!
 
- I encapsulate message sends to objects. Arguments can be either predefined or supplied when the message send is performed. 
 
- ## API
 
- Use `#value` to perform a message send with its predefined arguments and `#value:*` if additonal arguments have to supplied.!
 
- !MessageSend methodsFor: 'accessing'!
 
- arguments
 
- 	^ message arguments
 
- !
 
- arguments: aCollection
 
- 	message arguments: aCollection
 
- !
 
- receiver
 
- 	^ receiver
 
- !
 
- receiver: anObject
 
- 	receiver := anObject
 
- !
 
- selector
 
- 	^ message selector
 
- !
 
- selector: aString
 
- 	message selector: aString
 
- ! !
 
- !MessageSend methodsFor: 'evaluating'!
 
- value
 
- 	^ message sendTo: self receiver
 
- !
 
- value: anObject
 
- 	^ message 
 
- 		arguments: { anObject };
 
- 		sendTo: self receiver
 
- !
 
- value: firstArgument value: secondArgument
 
- 	^ message 
 
- 		arguments: { firstArgument. secondArgument };
 
- 		sendTo: self receiver
 
- !
 
- value: firstArgument value: secondArgument value: thirdArgument
 
- 	^ message 
 
- 		arguments: { firstArgument. secondArgument. thirdArgument };
 
- 		sendTo: self receiver
 
- !
 
- valueWithPossibleArguments: aCollection
 
- 	self arguments: aCollection.
 
- 	^ self value
 
- ! !
 
- !MessageSend methodsFor: 'initialization'!
 
- initialize
 
- 	super initialize.
 
- 	message := Message new
 
- ! !
 
- !MessageSend methodsFor: 'printing'!
 
- printOn: aStream
 
- 	super printOn: aStream.
 
- 	aStream
 
- 		nextPutAll: '(';
 
- 		nextPutAll: self receiver;
 
- 		nextPutAll: ' >> ';
 
- 		nextPutAll: self selector;
 
- 		nextPutAll: ')'
 
- ! !
 
- Object subclass: #MethodContext
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Methods'!
 
- !MethodContext commentStamp!
 
- 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.
 
- My instances are JavaScript `SmalltalkMethodContext` objects defined in `boot.js`.!
 
- !MethodContext methodsFor: 'accessing'!
 
- home
 
- 	<return self.homeContext>
 
- !
 
- locals
 
- 	<return self.locals || {}>
 
- !
 
- method
 
- 	^ self methodContext ifNotNil: [
 
- 		self methodContext receiver class lookupSelector: self methodContext selector ]
 
- !
 
- methodContext
 
- 	self isBlockContext ifFalse: [ ^ self ].
 
- 	
 
- 	^ self home ifNotNil: [ :home |
 
- 		home methodContext ]
 
- !
 
- outerContext
 
- 	<return self.outerContext || self.homeContext>
 
- !
 
- pc
 
- 	<return self.pc>
 
- !
 
- receiver
 
- 	<return self.receiver>
 
- !
 
- selector
 
- 	<
 
- 		if(self.selector) {
 
- 			return smalltalk.convertSelector(self.selector);
 
- 		} else {
 
- 			return nil;
 
- 		}
 
- 	>
 
- !
 
- temps
 
- 	self deprecatedAPI.
 
- 	
 
- 	^ self locals
 
- ! !
 
- !MethodContext methodsFor: 'converting'!
 
- asString
 
- 	^self isBlockContext
 
- 		ifTrue: [ 'a block (in ', self methodContext asString, ')' ]
 
- 		ifFalse: [ self receiver class name, ' >> ', self selector ]
 
- ! !
 
- !MethodContext methodsFor: 'printing'!
 
- printOn: aStream
 
- 	super printOn: aStream.
 
- 	aStream 
 
- 		nextPutAll: '(';
 
- 		nextPutAll: self asString;
 
- 		nextPutAll: ')'
 
- ! !
 
- !MethodContext methodsFor: 'testing'!
 
- isBlockContext
 
- 	"Block context do not have selectors."
 
- 	
 
- 	^ self selector isNil
 
- ! !
 
- Object subclass: #NativeFunction
 
- 	instanceVariableNames: ''
 
- 	package: 'Kernel-Methods'!
 
- !NativeFunction commentStamp!
 
- I am a wrapper around native functions, such as `WebSocket`.
 
- For 'normal' functions (whose constructor is the JavaScript `Function` object), use `BlockClosure`.
 
- ## API
 
- See the class-side `instance creation` methods for instance creation.
 
- Created instances will most probably be instance of `JSObjectProxy`.
 
- ## Usage example:
 
- 	| ws |
 
- 	ws := NativeFunction constructor: 'WebSocket' value: 'ws://localhost'.
 
- 	ws at: 'onopen' put: [ ws send: 'hey there from Amber' ]!
 
- !NativeFunction class methodsFor: 'instance creation'!
 
- constructor: aString
 
- 	<
 
- 		var native=eval(aString);
 
- 		return new native();
 
- 	>
 
- !
 
- constructor: aString value:anObject
 
- 	<
 
- 		var native=eval(aString);
 
- 		return new native(anObject);
 
- 	>
 
- !
 
- constructor: aString value:anObject value: anObject2
 
- 	<
 
- 		var native=eval(aString);
 
- 		return new native(anObject,anObject2);
 
- 	>
 
- !
 
- constructor: aString value:anObject value: anObject2 value:anObject3
 
- 	<
 
- 		var native=eval(aString);
 
- 		return new native(anObject,anObject2, anObject3);
 
- 	>
 
- ! !
 
- !NativeFunction class methodsFor: 'testing'!
 
- exists: aString
 
- 	^PlatformInterface existsGlobal: aString
 
- ! !
 
- Object subclass: #Timeout
 
- 	instanceVariableNames: 'rawTimeout'
 
- 	package: 'Kernel-Methods'!
 
- !Timeout commentStamp!
 
- I am wrapping the returns from `set{Timeout,Interval}`.
 
- ## Motivation
 
- Number suffices in browsers, but node.js returns an object.!
 
- !Timeout methodsFor: 'accessing'!
 
- rawTimeout: anObject
 
- 	rawTimeout := anObject
 
- ! !
 
- !Timeout methodsFor: 'timeout/interval'!
 
- clearInterval
 
- 	<
 
- 		var interval = self["@rawTimeout"];
 
- 		clearInterval(interval);
 
- 	>
 
- !
 
- clearTimeout
 
- 	<
 
- 		var timeout = self["@rawTimeout"];
 
- 		clearTimeout(timeout);
 
- 	>
 
- ! !
 
- !Timeout class methodsFor: 'instance creation'!
 
- on: anObject
 
- 	^self new rawTimeout: anObject; yourself
 
- ! !
 
 
  |