codefrau / squeakjs Goto Github PK
View Code? Open in Web Editor NEWA Squeak Smalltalk VM in Javascript
Home Page: https://squeak.js.org
License: MIT License
A Squeak Smalltalk VM in Javascript
Home Page: https://squeak.js.org
License: MIT License
Do you think that it would make sense to split the source files into smaller pieces for easier source code management and organization? I tried to extract the internal plugins, interpreter, primitives etc. into standalone files as you may see here:
https://github.com/pavel-krivanek/pavel-krivanek.github.io/tree/master/pharo8/js/squeakjs
I guess it would make the managing of the code harder with Lively-Kernel but it seems that it is unfortunately dead these days and the next Lively versions like lively4-core are very different. So the better support for standard JS tools should be considered.
Currently, if an image/changes pair is delivered via ZIP, and then updated, the new ZIP is not downloaded and unpacked, and the old image/changes are used (tested with Chrome 54).
Reported by Klaus D. Witzel:
jumpIfTrue and jumpIfFalse both send SelectorMustBeBoolean to the wrong object on the stack, they assume mustBeBoolean has 1 argument.
In the example, 'hello' zork: (nil ifTrue: []), which is intended to fail, the VM should send to nil but sends to the string.
There are two possible calling conventions of the <primitive 100>
that have different arguments count:
Object>>#perform:withArguments:inSuperclass:
Context>>#object:perform:withArguments:inClass: (ContextPart)
The SqueakJS knows only the first one
Right now all files need to be served separately over http. It would be nice to be able to specify a zip file instead. It would have to be decoded using some JS zip library.
This would allow to cut down on the bandwidth (e.g. for the initial Etoys and Scratch downloads) and we could link to zipped Squeak images directly (e.g. http://files.squeak.org/5.0/).
E.g. using https://github.com/dropbox/dropbox-js
The web browser wipes out our "persistent" files if the disk space goes low. Also, if we had a way to "log in" our files could be shared across different browsers/devices.
Implementation-wise, files should be uploaded in the background. File download should happen on-demand, perhaps using the existing "templates" code. That would mean directory information would have to be fetched on startup.
We are missing the better LocalePlugin implementation for:
locale_primitiveTimezoneOffset
locale_primitiveTimezoneOffset
I used these stubs for now:
locale_primitiveTimezoneOffset: function(argCount) {
this.vm.popNandPush(argCount, 0);
return true;
},
locale_primitiveTimezoneOffset: function(argCount) {
this.vm.popNandPush(argCount, 0);
return true;
},
Adding the library to http://cdnjs.com would make it much easier for developers to include it in their websites since they wouldn't have to host and update it themselves. This would be great since SqueakJS seems to be updated rather quickly.
There are various websites with Etoys projects (e.g. http://squeakland.org/showcase/ or http://etoysillinois.org/library or http://emergent.de/etoys.html ) that cannot be viewed without the plugin. A chrome extension could recognize the project links and offer to view them in SqueakJS.
E.g. in a 4.5 image running
MessageTally spyOn: [10 timesRepeat: [(2 raisedTo: 100000000) basicSize]]
gives
100.0% {3441ms} EventSensor>>eventTickler
100.0% {3441ms} Delay>>wait
Perhaps there is something wrong with process switching?
I have put my current version of SqueakJS on node on my Github repo. I have not created a PR, because the changes are quite big and may need some adjustment to be in line with your preferred approach.
You can find it at: https://github.com/ErikOnBike/SqueakJS/tree/nodejs
I also put up a Gist where you can find a Cuis image which will run from SqueakJS on node. It will interact with a Node WebSocketServer which will display a prompt, allowing to send Smalltalk expressions to the Cuis image (in SqueakJS). Pretty cool if I might say so myself :-).
Gist: https://gist.github.com/ErikOnBike/ae10d81ed19500f24f155c086b3d7c09
Let me know what you think!
Reportedly it fails when visiting https://codefrau.github.io/SqueakJS/demo/simple.html#document=JSBridge.st the first time. Works after reload. Haven't been able to reproduce reliably yet.
Squeak 5 is in Spur format, we need to support it.
It's [Alt Gr] + [Q] for me under Windows 8.1.
Maybe we need another hack than content-editable? It works fine on desktop Chrome though.
We do not implement primitiveFetchMourner (172) in the new primitives. I use this workaround to do not let it fail in Pharo:
case 172: if (this.oldPrims) return this.namedPrimitive('SoundPlugin', 'primitiveSoundStop', argCount);
else return this.popNandPushIfOK(argCount, this.vm.nilObj); //primitiveFetchMourner
If SqueakJS is invoked with a set of files as specified in the URL, those files will not be downloaded/updated if the browser cached them already:
https://bertfreudenberg.github.io/SqueakJS/run#url=<url-to-files>&files=[<some-files>]
It would be nice to provide an additional option to force a reload. Maybe this: &forceReload=true
Maybe use https://github.com/eligrey/FileSaver.js/
The primitive primitiveHashMultiply from the set of new primitives is missing. It should at least fail. I use this workaround:
case 159: if (this.oldPrims) return this.primitiveFileRename(argCount);
else return this.primitiveHashMultiply(argCount);
where this funciton is defined behind primitiveNotEqualLargeIntegers as:
primitiveHashMultiply: function(numArgs) {
false;
},
It'd be great to have a testing setup for SqueakJS.
This testing setup could run SUnit
tests and/or other JavaScript tests.
Probably using Travis CI to be able to test pull requests in advance.
I'd like to call a Smalltalk method from within my Javascript plugin (instead of using Semaphore to signal some event). I tried something like shown below, but I end up in a debugger showing me a DNU for a method on an object/class I am not referring to directly.
// Trying to do a sort of #perform: with the argument of the named primitive within the plugin
primitiveTest: function(argCount) {
if (argCount !== 1) return false;
var selector = this.interpreterProxy.vm.stackValue(0);
this.interpreterProxy.vm.push(this.interpreterProxy.vm.receiver);
this.interpreterProxy.vm.send(selector, 0, false);
// ...probably need to remove the pushed receiver, but popping here does not give correct result
// Normal behavior for popping the arguments and setting the result of named primitive function
this.interpreterProxy.popthenPush(argCount, this.interpreterProxy.nilObject());
return true;
}
The selector in the above has the correct Symbol. The DNU is for a message which IS send from the method belonging to the selector I'm trying to perform. So it seems as if 'self' within the performed method is not tied to 'receiver' but to the outer context (the instance performing the method which invoked the primitive). The following method is called, but a DNU for #log: is reported on some other instance (not the receiver).
mySelector
self log: (3 + 4) printString
Could not find any similar situations in the existing code base. Any advice would be highly appreciated! Is this approach not possible? Is using a semaphore to trigger some Smalltalk code for doing the #perform the regular/right way of doing this?
Named primitive calls are 10x slower than numbered primitives right now.
See http://lists.squeakfoundation.org/pipermail/vm-dev/2015-June/018879.html and http://lists.squeakfoundation.org/pipermail/vm-dev/2015-June/018889.html
Should produce a third-mouse-button event.
Pharo on vanilla SqueakJS has no active inputs. The image is not responsive to events. The Craig's version does some changes to the method primitiveInputSemaphore:
primitiveInputSemaphore: function(argCount) {
var semaIndex = this.stackInteger(0);
if (!this.success) return false;
this.inputEventSemaIndex = semaIndex;
window.interpreter = this;
this.display.signalInputEvent = function() {
this.signalSemaphoreWithIndex(this.inputEventSemaIndex);
}.bind(this);
this.display.signalInputEvent();
return true;
},
The problem is that in recordMouseEvent, the eventQueue is not set and so signalInputEvent is never executed
We now declare 54 parameters for the VM in Spur, It should be probably 71
var paramsArraySize = this.vm.image.isSpur ? 71 : 44;
Hi Vanessa,
Just putting it here for others to see as well. Maybe someone is interested to participate as well.
Cheers,
Erik
Etoys is integrated in Sugarizer, but does not store into its journal yet: llaske/sugarizer#64
When you cmd-tab away from Squeak, it gets the cmd-keydown event but not the cmd-keyup. So when returning it still thinks the cmd key is pressed, so you have to press cmd again.
I guess we need to also fetch the modifier key state from the event, not just look for keydown/keyup.
on https://squeak.js.org/scratch/#fullscreen the language menu (globe icon) creates a menu with a malformed marker that looks like ,รยข
. That probably is a 3-byte UTF-8 sequence that is not properly decoded.
To reproduce, add delete window.indexedDB;
after this line and then run Etoys.
... because controlling the pointer with touch is not accurate enough for Squeak images that are intended to be used with a mouse.
... using 53 bit logic, as in e3627a0?
e.g. http://bertfreudenberg.github.io/SqueakJS/etoys/#fullscreen&document=https://crossorigin.me/http://www.emergent.de/pub/smalltalk/squeak/projects/1415Puzzle.001.pr
logs the error image segment format not supported
.
Amazing project! It would be nice if the Mini image contained more of the functionality needed to work through the classic "Smalltalk-80: The Language" by Goldberg & Robson. For example I tried some of the Polygon
examples and the Polygon
class was missing. Also Pen
did not respond to location
etc.
So far, there is no networking support (except via the JSBridge). It would be awesome if socket connections could be opened, but it's not quite clear how this could work. WebSockets are a possibility but are hampered by the browser's security restriction. Possibly a proxy server is needed.
This is working fine:
HTTPSocket httpGet: 'http://source.squeak.org:80/squeak45/
but this fails:
HTTPSocket httpGet: 'http://source.squeak.org/squeak45/' args: nil user: '' passwd: ''
This is with the https://crossorigin.me/ proxy and using the fetch
API.
The proxy does not grant the requested Access-Control-Request-Headers: authorization
, it sends back Access-Control-Allow-Headers: Content-Type
instead. This appears to be ignored by XMLHttpRequest
but fetch
reports an error.
Reported by Jerry Bell at http://lists.squeakfoundation.org/pipermail/vm-dev/2015-January/017585.html
I'm trying to run the JSBridge callback example from a 4.5 image. JSBridge.st is loaded and I'm running under Chrome on Windows. I get an error: "Error:primReturnFromCallback: failed. " Digging a little in the debugger, I find in JSObjectProxy>>handleCallback, result is : "Error: Error: This block accepts 2 arguments, but was called with 0 arguments".
Modifying the example with a callback block with 0 arguments works.
When visiting https://bertfreudenberg.github.io/SqueakJS/run/, the browser refuses to load images via http://
.
Mixed Content: The page at 'https://bertfreudenberg.github.io/SqueakJS/run/#url=http://freudenbergs.de/โฆkjs&files=[Squeak4.5-13680.image,Squeak4.5-13680.changes,SqueakV41.sources]' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://freudenbergs.de/bert/squeakjs/Squeak4.5-13680.image'. This request has been blocked; the content must be served over HTTPS.
Providing images through https://
will solve the problem.
For now we download the whole file first before passing it on to the image. We should start delivering data as soon as it arrives. This would allow the image to display proper progress, and potentially reduce memory consumption.
Since we're dealing with binary data we might have to use the fetch api, which isn't widely supported yet. So this needs to be optional.
E.g. this brings up an emergency evaluator: https://bertfreudenberg.github.io/SqueakJS/demo/simple.html#document=JSBridge.st
Bisecting points to pull request #30 as the culprit. We'll have to fix it, or pull out again.
I used these VM parameters implementation for Pharo that tries to read them
// 46 size of machine code zone, in bytes (stored in image file header; Cog JIT VM only, otherwise nil)
case 46: return 0;
// 49 the size of the external semaphore table (read-write; Cog VMs only)
case 49: return null;
// 65 In newer Cog VMs a set of flags describing VM features,
// if non-zero bit 0 implies multiple bytecode set support;
// if non-zero bit 0 implies read-only object support
// (read-only; Cog VMs only; nil in older Cog VMs, a boolean answering multiple bytecode support in not so old Cog VMs)
case 65: return 0;
Currently we always try a direct request first, and the proxied one second. In some situations this leads to considerable delay (e.g. 2 seconds on source.squeak.org).
We might want to keep a table of hosts and their need-proxy flag. Whenever a request succeeds we put a flag for that host in the table. When another request comes in and we have a flag already then we use the order (proxy/direct first) given by the flag, otherwise we try direct first.
None of the sample images on this page will load: http://squeak.js.org/run/
the popup message is: "failed to download [specifiec URL]"
hi,
what do you think about compile some parts of squeakjs in asm.js. For example the canvas rendering code.
I don't konw if this ideas has been explored. What do you think about?
Only works in Chrome right now. We probably want a hidden text field.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.