| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729 | 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.## API1. 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.## APIMy instances can be accessed using `Behavior >> #methodAt:`    Object methodAt: 'asString'Source code access:	(String methodAt: 'lines') sourceReferenced classes:	(String methodAt: 'lines') referencedClassesMessages sent from an instance:		(String methodAt: 'lines') messageSends!!CompiledMethod methodsFor: 'accessing'!arguments	<return self.args || []>!category	^ self protocol!fn	^ self basicAt: 'fn'!fn: aBlock	self basicAt: 'fn' put: aBlock!messageSends	^ self basicAt: 'messageSends'!methodClass	^ self basicAt: 'methodClass'!protocol	^ (self basicAt: 'protocol') ifNil: [ self defaultProtocol ]!protocol: aString	| oldProtocol |	oldProtocol := self protocol.	self basicAt: 'protocol' 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 ] ]!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'!defaultProtocol	^ 'as yet unclassified'! !!CompiledMethod methodsFor: 'evaluating'!sendTo: anObject arguments: aCollection	^ self fn applyTo: anObject arguments: aCollection! !!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.## APIThe 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:`## APIBesides 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. ## APIUse `#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'!evaluatedSelector	<return self.evaluatedSelector>!home	<return self.homeContext>!index	<return self.index || 0>!locals	<return self.locals || {}>!method	^ self methodContext ifNotNil: [		self methodContext receiver class lookupSelector: self methodContext selector ]!methodContext	self isBlockContext ifFalse: [ ^ self ].		^ self outerContext ifNotNil: [ :outer |		outer methodContext ]!outerContext	<return self.outerContext || self.homeContext>!receiver	<return self.receiver>!selector	<		if(self.selector) {			return smalltalk.convertSelector(self.selector);		} else {			return nil;		}	>!sendIndexAt: aSelector	<return self.sendIdx[aSelector] || 0>!sendIndexes	<return self.sendIdx>!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`.## APISee 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}`.## MotivationNumber 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! !
 |