I recommend anyone wanting to experiment with WASM to check out https://github.com/dcodeIO/webassembly which takes a lot of pain out of setting up the toolchain and lets you produce much leaner binaries as well.
Thanks for the link, I would probably have tried this had I stumbled on it before! I did an ask HN prior to writing this article but did not get that much answers: https://news.ycombinator.com/item?id=14483383
This AssemblyScript thing looks like some nice idea for being able to work with a single language while still being able to compile some computationally-heavy but otherwise small modules down to WASM and using them later from JS/TS as an external module.
I'm curious how this approach looks from an optimization point of view? I guess emscripten/LLVM can do more optimization than this the AssemblyScript/binaryen toolchain, and when one puts already the effort in for using WASM the goal should probably be to have as much optimization as possible.
Hard to be sure without measurements, but emscripten uses LLVM's optimizer and the binaryen optimizer, and AssemblyScript can benefit from the latter. So the question is how much the LLVM optimizer could help this type of code.
For example, the LLVM optimizer can do smart things with aliasing and assumptions about undefined behavior in C code, but for a language like AssemblyScript those might not be relevant anyhow.
But currently the binaryen optimizer is still missing some passes like GVN, so until we add those, that might be noticeable when doing comparisons here.
I wonder how it would be, had capability-based system architectures taken off and become mainstream. I guess we wouldn't need WebAssembly to run untrusted code safely, because in such a system, all objects – from whole programs to an object as small as the number 4 – would be safe and sealed off from each other on a hardware level.
I'm reading Capability-Based Computer Systems [0] by Henry M. Levy (1984), motivated by wanting to learn about the Burroughs B5000 that Alan Kay has praised multiple times. I've only started to learn about these things and I don't understand the implications, but if I'm reading it correctly, such architectures would obviate the need for web-style safety measures such as process-sandboxing ala Chrome, shader sanitizing ala WebGL, etc, because everything in the system would be safe that way.
In case you don't have it yet: "the Burroughs B5000 conference" (http://conservancy.umn.edu/bitstream/handle/11299/107105/oh0...) is a transcript of a set of discussions held in 1985 by people involved in creating the B5000. I found it an interesting read. Abstract:
"The Burroughs 5000 computer series is discussed by individuals responsible for its development and marketing from 1957 through the 1960s in a conference sponsored by AFIPS and Burroughs Corporation.
In the first session the technical aspects of the B 5000 and 5500 are discussed by a group of managers, engineers, and consultants. Topics include: the state of the industry in the late 1950s; the 5000's predecessors, particularly the ElectroData 101 and 201, B 205, and B 220; factors influencing the decision to produce the B 5000; reasons for designing the machine for ALGOL rather than FORTRAN and the effect of this decision on the computer's development and sales. The group reviews the MCP operating system, PERM, Polish notation, descriptors, stacks, the BALGOL compiler, and other innovations of the computer.
In the second session, the same group discusses the development of the B 5000 into a product, including the effect of the administrative organization on the project; the relations between hardware and software engineers; the interaction of project personnel and upper-level management, field marketing, and customers; the COBOL processor, the head protract disk system; the operating system; ALGOL; and documentation of the computer.
In the third session managers, sales personnel, and customers of the B 5000 discuss Burroughs' product line before the 200 and 5000 series computers; sales training and market reaction to the B 5000; acceptance of B 5000s at Ohio Oil Company and Stanford University; its rejection by the University of Michigan; reasons why the B 5000 was not marketed overseas; and Burroughs' presidents Raymond Eppert and Ray MacDonald."
'Sandboxing' within single processes would still be necessary, at least (and I suspect at many other levels too, practically). I think it is necessary now, but that is not (yet?) appreciated.
If you haven't seen it already, I and many better educated people recommend http://www.erights.org/talks/thesis/ (a pleasant read, even if I don't judge it by comparison with other theses) - focuses on distributed computation and language-level capabilities
On display in the bottom of a locked filing cabinet stuck in a disused lavatory with a sign on the door saying ‘Beware of the Leopard.”, is this mailing list:
To be honest: Yes? I would say that is the conventional wisdom in the (small) capability community. I'm sure that oversimplifies carefully-nuanced opinions of course, but, yes.
An example is mentioned here ('angels', 'Power Boxes'):
The idea is that capability-based user interfaces do not need to ask those "Yes, get my work done/No, be secure" questions in the first place. That idea will be better tested if they ever take off in more than the isolated areas they're currently found of course.
Capability security has low adoption in part because of the usual catch-22 (adoption breeds adoption), in part because it's a tricky challenge to retrofit, and in part I think because of a failure to communicate the ideas to the best and most influential implementers - exactly why I don't know.
> and in part I think because of a failure to communicate the ideas to the best and most influential implementers - exactly why I don't know.
I agree here, that page is the perfect example, all I see is a page full of academic buzzwords and not a "How this works in practice". So we limit what resources an app has access to, that's easy enough to understand, but what happens when an app needs resource x? Does it have to prompt the user or does it have to have to be granted the access at install time? As far as I'm aware those are the only two options.
> The idea is that capability-based user interfaces do not need to ask those "Yes, get my work done/No, be secure" questions in the first place. That idea will be better tested if they ever take off in more than the isolated areas they're currently found of course.
It sounds like it has to prompt users to get permissions:
> This includes a KDE-based PowerBox scheme allowing sandboxed applications to request user-driven file open using standard dialogs.
> It sounds like it has to prompt users to get permissions:
Well, in some sense, yes, but really no: The idea of a PowerBox is that the very action of opening a file already demonstrates the user's intent to grant access. Normally one does not conceive of opening a file as a prompt for permission, because it is necessary to designate a file in the first place.
As long as the thing that is being granted access is isolated and nothing else grants it access, problem solved.
It's a very neat idea, and it works.
This goes along with the capability slogans "No ambient authority", and (stronger) "No designation without authority".
Here's an old talk with demonstrations by Marc Stiegler, who I believe came up with the concept:
More recently I hear essentially the same idea has been used in mobile phone security (I don't have that kind of mobile phone). The capability ideas that surround it are not widely known or understood, though.
Thanks for the video, I'll give it a watch when I'm not at work, so apologies if any of the below is covered by the video.
> Well, in some sense, yes, but really no: The idea of a PowerBox is that the very action of opening a file already demonstrates the user's intent to grant access. Normally one does not conceive of opening a file as a prompt for permission, because it is necessary to designate a file in the first place.
That's fine in simple cases, windows store apps already work this way, but what about something like an IDE where you want to open many files? I suppose granting permission at a folder level is possible, but then what about something like vim where I want to switch between files and there is no file open dialog? What happens when I want to install an a different file browser that needs global read/write abilities?
> This goes along with the capability slogans "No ambient authority", and (stronger) "No designation without authority".
How does that work with something like an IDE? You have to pass the compiler a bunch of files names and you'd have to pass the access permission with them, then compiler has to create a new executable with the ability to run and pass the access back to the IDE. And that's just for the simple case. For that matter, how does it work with command line tools that pipe file names between them? Every demo and implementation I've seen appears to be under the impression that apps are self contained.
> what about something like an IDE where you want to open many files?
I can't call myself a capability programmer, but I can take a stab at that:
First, and this sounds glib, but it isn't: one has to decide what the program needs, and arrange that users can grant it that, but not more (of course this is an ideal not a reached endpoint, but I don't want to apologize for an under-applied principle). This is the principle of least authority. Programs, and objects, can't operate without the authority they need. According to cap adherents, most of the work in designing and implementing more-secure systems should be in the detailed working out of what is needed and how objects and programs talk to each other, passing authority to and fro in the process.
To apply the powerbox UI pattern and similar patterns, it isn't necessary for there to be a literal dialog, and in fact a good place to start is: 'what is the UI now, if I were to remove all UI associated with "security"'? So for vim, why not :e? A goal could be to drop the parts where you have to run sudo and type in your password (or maybe there are parts of vim where vim prompts for your password so vim can do that for you, using the resulting ambient authority). Powerbox-like principles have been applied to the command line (e.g. plash; there are more recent systems). That is UI too.
UI patterns, access granularity (e.g. your example: directory cap or file cap?) and access control patterns have to match the problems you want to solve in all their product-/domain-specific detail, like any other part of software engineering. So, if say all you are concerned with is constraining read access on the file level, "opening many files" one at a time and then subsequently "switching between files", there is nothing more to do, and "granting directory access" is not necessary (though it wouldn't imply creeping ambient authority, just coarser-grained access). Only the powerbox needs access to the directory. If you're writing an IDE, there will of course be parts of the IDE that deal with directories. The task of applying object capabilities pervasively to systems like that involves going a long way past the powerbox, and expressing in language-level objects what each part of the system needs and how it obtains and passes on that access (with dramatically lower friction than we commonly have easy access to today). The task of getting the software industry to the the point where that is commonplace involves creative shortcuts that are both useful and feasible, like Google Caja and SES, sandstorm, plash, capdesk, etc (Caja and SES is unusual in advancing both these tasks). How to do that well starting with existing IDEs is a project for an inspired person, not an HN comment, but I sketched some ways below :-)
If it's necessary to provide only temporary access, use patterns like membrane.
While "omit the 'security UI" is a good place to start, Mark Miller (Google Caja, ECMAScript committee, etc.) has said that software security took a wrong turn some time around 1960 (I may be out by a decade or so). If you take that seriously, you should expect that capability security is behind in finding UI patterns that are well-optimized to a parallel world in which obj cap UI and the infrastructure that supports it has been hammered on by creative people for 60 years. ACL UI has been through that process of enormous effort and talent applied to this world in which almost everything is done using ACL security. So, if one wants to find the truth of whether obj caps can provide objectively better UI and security, I'd say the only way to answer those questions is to invent the answers, and see how they hold up. Of course it's made more of a challenge by the need to find the right small steps, and not rewrite all software! But there are plenty of projects that have shown that's possible technically. If you want a path where you don't have to invent new stuff just to stay afloat: of course don't use capabilities.
You may well appreciate this already, but there's an irony to hearing "windows store apps already work this way" (same for iPhone I believe: that's what I was referring to) when for the longest time, a few people knew how to solve the problem, even that was not implemented in real systems. We still don't apply the same lessons in most of software engineering. In fact, I don't know if most of the people who applied it to those mobile systems even knew that what they were doing is called capability security. For me the lesson to take from mobile phone use of powerbox-style UI is that capability-style security patterns work, and that if we applied it, knowing that's what we're up to, I bet that there is much more progress to be had in that direction.
How would you change vim to support just :e-as-powerbox, in a not-yet-cap-friendly world? That's a challenge! Maybe you'd take a heavy, sandboxing approach that tries to cut out the work to make vim use capabilities internally. So perhaps process-level sandbox gvim, pull out the ex line handling into a library, and dynamically link an unsandboxed process that provides an X window that replaces the ex line. Obviously there would be plenty of things to work out there! Similar things have been done before however: e.g. I recall plash also supported sandboxing firefox with a powerbox injected dynamically via LD_PRELOAD (with limited isolation: sandboxing has moved on since then) -- but I would expect vim to be hard. But on past history I am probably missing a trick.
Perhaps more ambitious (I'm not sure), but much more powerful and scalable, maybe you'd choose to start with spacemacs instead of vim, and design an object-capability subset of elisp that still leaves it feasible to port enough elisp to get the project off the ground. Workable obj cap subsets like this, that can interoperate with old code, have been done for other languages (notably JavaScript).
> What happens when I want to install an a different file browser that needs global read/write abilities?
How would you swap out file browsers? In general a good answer is dependency injection. More detail would be getting into detailed software engineering and very specific choices, not to mention the current software landscape (again, the LD_PRELOAD hack is an example). I don't think there is anything intrinsically harder about that with caps than non-cap techniques: in fact the opposite, because capability discipline requires good separation of concerns, and therefore at least encourages dependency injection.
Global read/write abilities? Not sure I follow what you are thinking: A plain-old powerbox typically has global read/write abilities (or only read, if that's what you want). The objects or programs that use the powerbox do not, because they have no means to do so except through the user granting that, using the powerbox. Of course a particular cap system might restrict that further if that was appropriate in the domain.
> How does that work with something like an IDE? You have to pass the compiler a bunch of files names and you'd have to pass the access permission with them, then compiler has to create a new executable with the ability to run and pass the access back to the IDE. And that's just for the simple case. For that matter, how does it work with command line tools that pipe file names between them?
It isn't necessary for compilers to use file names to get access to files, and in fact that's a clear violation of capability discipline: it involves ambient authority. In fact this very example with compilers and file paths happens to be historically the original example of a general situation that causes a whole category of bugs that can be prevented by use of capabilities: see the "confused deputy problem", and the wikipedia entry on ambient authority. For command lines, take a look at plash (or more recent related efforts if that's not on the web any more... if you can't find them, reply and I'll dig). Or just consider this simple example from plain old shell, sans capabilities (from David Wagner):
$ cp foo.txt bar.txt # cp must run with all of the user's authority
$ cat < foo.txt > bar.txt # cat needs no authority other than what's given to it
(this doesn't imply that compilers need be ignorant of file names, by the way)
By the way, it's instructive to consider why that last example isn't a tiny capability system.
The answer is: it is a capability system -- or would be, except that something has been ADDED to that clean cap system, which is the ambient authority provided by the open() system call. If not for that (and similar), cp in that second example would be unable to access other files than those.
plash implemented a shell lacking that ambient authority (with limitations due to limited sandboxing at the time) by means of sandboxing at the command level. If I recall correctly you could use it with commands like the first one above, but the resulting semantics were more like the second command: cp could only read foo.txt, and only write bar.txt. In a capability OS (like Google Magenta?) that sandboxing would not be necessary (but OS-level caps are only part of the cap story).
> I agree here, that page is the perfect example, all I see is a page full of academic buzzwords and not a "How this works in practice". So we limit what resources an app has access to, that's easy enough to understand, but what happens when an app needs resource x?
If you're interested in more/different examples than the Stiegler talk, google ka ping yee capability ui patterns
Remember when you could hit "View Source" to see how the web was built? I don't like where this is going. Minification was bad enough, now we're going to be getting more non-free blobs shoved into our browsers and this is being touted as a great new feature for us.
It will end up being a tool of control and surveillance like always.
This guy says it a bit more eloquently than I can:
Bullshit. Wasm can't do anything js can't. Especially with asm.js. Don't try to argue that minified or transpiled js is somehow more readable than wasm. At least it's easier to decompile in theory.
It's absolutely not a "tool for surveillance". How exactly are you going to surveil anything with it?
It's not even a replacement for js, or at least it shouldn't be used that way. No GC for instance. And if you are doing any of the silly things mentioned in your link you have no one to blame but yourself. Like accepting binary blobs without source from contractors.
The link eventually admits you can't do a lot of stuff with js and should use native code. Great, lets just have everyone download and execute untrusted and unsandboxed code. In a way that is completely incompatible across platforms. Maybe we can maked them locked behind "walled gardens" with a ridiculous tax while we're at it. Future generations will laugh at us from their completely wasm based PCs.
Or we can always go back to the old way of doing anything interesting with a browser. By making proprietary, vulnerability ridden plugins. Don't you just miss the days of flash and java applets? Because surely that was a much better solution than wasm.
Yep. WebAssembly today is literally just a better/faster asm.js.
The argument against it linked above is nonsense. Most arguments like this that I see tend to fall into one of these boxes:
1. Using wasm as springboard to argue against something else they don't like.
— e.g. disliking closed source code / source obfuscation / minification is a fair position, but it's not helpful to anyone to pretend that wasm introduces anything different here (as has been pointed out, wast's inclusion of type information actually makes it slightly more readable than minified JS).
2. Arguing against something that wasm could maybe one day become.
— Right now wasm doesn't enable anything you can't already do with asm.js, so the idea that it somehow kills JavaScript or whatever is wrong; anything that can compile to wasm can compile to asm.js. Sure, maybe one day wasm will gain DOM/GC/etc. functionality, but asm.js could just as easily gain a lot of the same proposed features. (And wasm/asm.js aside, plenty of languages already compile to JS quite successfully; this hypothetical future wasm would just make them faster.)
3. Seeming to have only a vague sense of what wasm actually is. I think arguments like #1 and #2 have led to a set of talking points that don't at all reflect reality but sound correct to developers who don't have direct experience with asm.js/wasm.
— e.g. the argument from the linked Lobsters comment that "It solves problems that we don’t have. ... If performance is the important thing you pull on your big kid pants and write C/C++/D/Rust and if ... performance isn’t important, you just write in JS." neatly summarises exactly the point of wasm while somehow trying to frame it as an argument against it.
And asm.js wasn't the correct answer either. Nor is minification, as is pointed out in my original comment.
On (1), you're ignoring the fact that asm.js/wasm/low-level languages are in general harder to reverse than uglified high-level stuff. You can see the details perfectly, sure, but emitted compiled code (say, from Duff's device or something) is a lot harder to back out of than the equivalent minified source code--especially when you see crazy shit like "-O 3" would make. tl,dr; compilation != minification, and acting like they are is at best incorrect.
Your (2) fails to address the entire complaint about wasm (aka asm.js) leading to bad things and ecosystem bloat. You just say "well we can kinda already do it", but fail to address any of the substance of the actual argument I made.
Your (3) misses the point completely about "write in native code" and not "write in something that gets run in an interpreter". Like, you've missed the whole point that if you need performance, you need to be writing something outside the browser, and if you don't need performance existing JS is sufficient.
1. Yeah, sorry, I was really speaking in general terms here and should've been more clear about that, as your argument was explicitly that it's just another step in a pre-existing wrong direction, not a big horrible thing all its own. re: wast vs minified JS, the specific comparison I had in mind was with asm.js code, which (minified or not) is from what I've seen less readable than wast.
Generally speaking, my point here was that I think some arguments against wasm conflate a pre-existing state of affairs that aren't liked
with the delta that wasm introduces.
2. Hm, yeah, fair enough. In my mind this all boiled down to "the only significant direct effect of wasm is to make what we're already doing faster", which in itself is obviously good; but that was coming from my bias of being a fan of asm.js, and ignored the other long-term impacts that would inherently come with enshrining all that extra machinery — even just politically blessing what asm.js already accomplishes in most browsers as the officially sanctioned new normal in all browsers isn't nothing if you think it will at least politically help in pushing things further in a bad direction.
I'll have to reread your and other arguments against wasm with a more open mind less stuck on the immediate delta.
And yeah, actual harmfulness or lack thereof aside, it wouldn't help anyone for all this effort and API surface expansion to go into building out a feature that didn't add value ("ecosystem bloat"), so that's a fair point.
3. I got what you meant by that, although on the first read it also sounded like there was some sort of misunderstanding (mostly combined with the "bad vendor incentives" section — it wasn't clear why a vendee would be more likely to accept compiled wasm without source code than minified/obfuscated JS). In any case, I don't see why being required to leave the browser for performance-sensitive code should be considered a feature and not a bug. Wasm presents a very convenient method of sandboxing untrusted code with a high performance requirement.
Agreed that this isn't a concern for typical CRUD apps or documents (although I imagine CRUD apps will ultimately benefit in the form of frontend JS frameworks incorporating wasm in critical paths), and I know I'm definitely in the minority being a beneficiary of asm.js/wasm. However, it's a bit late at this point to unmake all the more complicated applications we've built on the web, and all wasm does is improve a subset of those applications that already exist (as opposed to enabling entirely new applications), so I don't think this is a good argument against it.
After 20 years of web dev, I gave native development (UWP) a shot. I kinda assumed that after so much time Microsoft would have windows development dialed in and it would be sane. Ha!
Overall, not sure, part frustrated, part liking it.
Good
C# is fantastic
Between the Community Toolkit and Telerik's UWP UI, there are some fantastic open source controls available for reuse.
Bad
XAML editing can be frustrating, the visual state setters don't recognize the local properties, which leads to a lot of copy/paste and no help w/errors (e.g. TextBlock.RelativePanel.AlignTopWithPanel is wrong and should be TextBlock.(RelativePanel.AlignTopWithPanel), but intellisense gives no hint).
Using the new x:Bind I couldn't get blend to show design time data, it only showed the property names, which is misleading when you have a long property name holding a small string value.
There are a whole bunch of other little frustrations like those 2 above, the net effect of which is a minor aversion to the XAML side of things.
Yes, it's not ideal but remember the ultimate goal, having universal apps that run at native speed and don't have to be constrained to the few large app stores. I'll give up view source for that, assuming the browser VM they run in is secure of course.
Thank you for the link, you too had a very nice discussion.
However I find unsetting how Eich ends up defending WASM by hoping it's not too successful (used only in some hot pathes, not full blob apps.) That's frankly quite ridiculous: I predict a full apps adoption pretty soon. Just wait for more mainstream languages to support it.
The open web in the sense the OP meant has been dead for a while, WASM is just another tombstone.
You'll notice that basically everyone involved with WASM agrees that it won't be used for full applications any time soon if ever. It's only people who aren't as involved who are calling for it.
WASM is not a replacement for javascript, and it's not trying to be. You won't be writing entire applications in whatever you compile to WASM, it's not how it's designed, it's not how it's meant to run, and it's worse in most ways than just compiling your favorite language to javascript (which has been possible for a long time now, but nobody uses it because it's such a leaky abstraction).
The open web is flourishing more than ever, and WASM is keeping that alive with it's "text" mode.
I think there is no technical hurdle that is stopping browser manufacturers from downloading the bytecode and showing a disassembled view of it.
Plus nothing is stopping us from popularizing a trend where everybody puts a publicly discoverable debugging hints file (which would make the disassembly easier to read) with a fixed name next to all wasm files.
Would you be OK with having every website you visit run native byte-code on your computer !? At least for me, it takes some trust to install a native app. I don't trust some companies and would never let them run a binary blob on my computer, still I sometimes visit their web sites, with JavaScript turned off of course. Some sites require JavaScript though, but I can turn on selective parts (using NoScript plugin) and then investigate all the nasty stuff with the browser's built in debugger.
Political views aside, I think I understand a key difference in that, presuming one wants to run Free (Libre) software, it's relatively easy to do if you are running one of the FSF recommended Linux distributions.
By contrast, if in common usage people are only running software compiled to Web Assembly, then:
1. You probably have some work to do to figure out the licensing of the code running in your browser.
2. The ability to look at the program logic for study or reuse is diminished in practice as compared to the early web when you could view source.
1. is identical on linux distros. How many licenses are you using right now? Probably 20+ distinct licenses as a lowball guess. It's not easy to figure this out, and if it's something you and others really want, i'm sure a standard could be thought up to be able to on-demand get a list of software licenses used in a project which could then be built into browsers similar to sourcemaps.
2. might be more possible with WASM than it is with minified JS since WASM has a text mode which is very readable.
1. Eh, if I'm running, say, Ubuntu and haven't turned on the non-free stuff I can make some reasonable assumptions about my baseline rights.
2. I don't think anyone is claiming minified JS is awesomely transparent. WASM is certainly worse than the unobfuscated, unminified JS, which until not long ago was the norm.
WebAssembly in itself is not an enemy of freedom, as even Richard Stallman would agree.
The bigger problem, which is also a problem with web scripts in general, is that browsers and script distributors generally make no effort to inform users about what scripts are running, whether they are proprietary or free software, etc.
- Wasm (and JS) should have metadata (loadable before executing the code) declaring the license, and pointing to the source
- Browsers should whether site is open source (per OSI), and allow to block non-open JS. Or fake access to any sensitive APIs for non-open code (can still do DOM interactivity)
The builds should ideally be reproducible, and community-based third-party sites verify the output comes from said source. This would be another badge/warning/setting.
I'm trying to use asm.js to port Python to JS as a shared library, which would allow us to load and run arbitrary CPython modules (compiled for JS) in the browser. I generate code using emscripten, which is also able to generate WASM (which I'm not using at the moment though).
My experience so far:
Emscripten is quite mature and compiles even very complex C/C++ code without complaining. Statically linking code works fine, while dynamically loading shared libraries is still a bit problematic it seems.
Here's the Github project btw, help is very welcome:
Slightly disconcerted that the first thing webdevs are rushing to do with wasm is to port massive language runtimes to it, continuing the web tradition of piling shit upon shit upon shit. Personally believe that this is totally the wrong idea; compilation or transpilation from intermediate forms is far more interesting and sensible in my view
Sure when targeting the web with software that doesn't exist yet I would definitely write that in JS. However, if there is a well-tested crypto library that has 300.000 lines of well-tested C code and that I can use without too much pain by transpiling it to JS I'd always prefer that to writing my own implementation in JS. In that sense transpiling is a great way to reduce redundancy by allowing to use code in different context. Concerning the intermediate form: I'm a big fan of model driven development but I think our tooling for it isn't good enough yet, so until someone invents a description language that is really powerful enough to describe let's say a crypto library and then generate code from that in various languages I think transpiling from one concrete language to another is still a better option.
BTW a lot of the power of Python, Ruby and JS comes from the interface these languages provide to existing C/C++ codebases, and I assure you that the binding code to make this work is often far from pretty. As end users we don't care about this though as long as it works.
It's not like people are planning on using these in production. It's just some fun hobby projects that are useful for, say, online Python tutorials and stuff.
There's a fairly large class of scientific computing oriented apps where having a widely deployed and fast VM with CPython compatibility would be fantastic. Python (for better or worse) has a large library of open source computational libraries, but shipping an embedded CPython VM is a pain. As an example, I helped advise an undergrad working on a program to calculate collagen fiber orientation for biomedical research labs. Figuring out cxfreeze or other Python packaging systems took longer than writing the actual app.
Unfortunately JavaScript doesn't have broad scientific library support and grad students in non-CS fields don't always have the time to become versed enough in C/C++ to create a usable app. So CPython & associated C libraries ported to wasm could be quite useful... This could apply to R programs as well.
Re: grandparent, just because a project offends your sense of purity doesn't mean it isn't surprisingly valuable for others.
I think it's a bit more than that given that the project has amassed more than 16.000 commits so far.
You must not forget that JS does not provide support for many of the things that are required to run a C program (e.g. printing), so emscripten needs to take care of providing alternative implementations for all these things.
Oh, alright. We are speaking about two different things. I was thinking about compilation and specifically supporting complex language features which are mostly handled by a compiler frontend which is this case is clang. And it seems that you are thinking about runtime libraries (or the whole tool chain).
With a BBC Micro (6502, 1MHz) I was able to achieve about the same FPS (I was genlocked for UK PAL TV transmission so either 25FPS or 50FPS) but only for a 40x25 grid, using 6502 assembler embedded in BASIC!
I'll concede that I did not spend any time optimizing the C code, the focus was mainly on getting a working wasm module that integrated correctly with th js code. I'll probably have a look on this after work.
... I don't share your sentiment at all. I find this relevant to the subject matter as he is, albeit indirectly, mentioning the performance of WASM. I would be surprised if you got the same performance using just plain old js on the hardware he is referencing.
The JS/WASM may be limited to 60FPS if it is being forced to draw every frame, in which case it has to wait for the browser, it may be much faster.
CA are great fun to optimise, i've found ways to make them very fast in JS alone, by using pure state machine method with TypedArrays and sliding window algorithm. When letting it skip frames (only drawing when a frame is available) it can go far beyond generations per second... when you get to larger grids the ultimate optimisation is to use FFT, but on smaller ones there is too much overhead and sliding window is way faster.
Algorithmic optimisation is always better, but this demo works for the purpose of showing basic WASM compilation which was the authors intent, there may be an order of magnitude improvement if a different implementation was used.
I'm not sure that you could load JS on the BBC Micro!
The point as that for something running safely virtualised (and standardised) in a random browser and on a much larger canvas, the WASM implementation is very impressive.
I'd be inclined to agree. Unless the point was not to show off, but that a 30 year-old computer is as fast as the bleeding edge in browser rendering technology.
An unoptimised implementation says nothing about what WASM is eventually capable of. This is an apples-to-oranges comparison unless the WASM app were optimised for speed. (Also parent mentions a 40x25 display on the BBC Micro).
Game of Life implementations are ideal case studies for optimisation after Michael Abrash's graphics programming columns.
Unoptimised code says a lot, it's an indication of what we can expect of real world apps that will be mostly or entirely unoptimised. It's like theoretical vs real world java performance, in limited and optimised benchmarks it might produce fast code, but in real projects it doesn't.
And that's the best case, there are already people in this thread talking about compiling python to web assembly, any performance improvements over the current state of the web are going to be pissed away immediately.
> Unoptimised code says a lot, it's an indication of what we can expect of real world apps that will be mostly or entirely unoptimised.
Maybe but not in this kind of performance-sensitive application that spends most of its time in a tight inner loop. Then it really comes down to how optimised that inner loop is.
Given that this [1] runs easily at solid 60fps on Chrome, a pure software rasterizer written in pure JavaScript with some basic optimizations, I'm pretty sure that webasm is can do at least as well. The Beeb is not capable of anything remotely like that.
Not very reassuring that two of the first steps are "copy and paste this stuff from stack overflow to make it work", without any explanation as to why it's needed.
I was disappointed that this doesn't really explain what webassembly is, and the link that says 'if you don't know what webassembly is, click here' just redirects to a tank game with no explanation.
I thought maybe it was some way to write x86 assembly in the browser, but apparently it's a tank game.
I wonder where the world is going with this. At first glance it looks like webassembly is a potential faster replacement for javascript in the browser. However, javascript is an increasingly popular language everywhere. I'm not sure people will want to move away from it for most development. The part that is actually causing performance problems with web application is the HTML/CSS/DOM layer which was not designed as a UI widget library but as a document rendering and styling framework.
Webassembly/Webgl standardization enables the creation high performance replacements for HTML/CSS/dom.
We might end up with applications that are still mostly written in javascript but that call into new webassembly/webgl ui frameworks for rendering instead of into the html/css/dom layer.
For me the main potential of asm.js/WebAssembly does not lie in the fact that it is faster, but in that it provides us with a way to run native C/C++ code inside the browser without adapting it (much), and doing this at a speed which is not (much) worse than the speed of the original code.
This in turn makes functionality that was traditionally very hard to get in a browser/JS environment suddenly very easy to get:
- Cryptographic libraries (e.g. libcrypto)
- Libraries for numerical data manipulation and analysis
- Compression libraries
- Video codecs
- ...
This ability will lead to a paradigm shift (IMHO), because instead of having to reproduce all this functionality in JS (which would be crazy) you can just cross-compile it and use it right away. Also, with WebAssembly, browser vendors can simply focus on providing good and secure interfaces to a limited amount of low-level functions (IO, graphics) while letting the user define the high-level usage of these interfaces. If this works out well I can even imagine this technology spilling over to other domains, because what it provides is essentially a secure, portable, low-level sandbox with a very good performance and a huge installation base.
This is the exciting new world I am thinking (hoping?) might happen. If this web assembly thing ends up being a success, the web is going to start taking an even larger slice of the development pie.
There will still be a place for native apps of course, but that place will IMO be much smaller.
There might be situations when you want client-side crypto not for sending data over the network, but to securely encrypt a document that you want to send / use in a different context. Using an emscripten-compiled crypto library would allow you to do this in your browser without sending any of the data over the wire.
I'd wager a lot of this popularity is correlation, not causation. A lot of its popularity stems from being the dominant browser scripting language. This causes it to be popular with back-end frameworks for code re-use and shared developer skill. This causes it to be popular with, say, database engines that are used by the back-end, and so on and so forth.
WebAssembly is the first steps to truly breaking that chokehold, and truly seeing how popular JavaScript the language really is.
JavaScript is easy to debug and test, its relative safe, and closures makes it easy to write async programs. Compared to C or C++ you'll have a huge productivity boost with a very small performance penalty. It's also easy to learn compared to other languages. It also doesn't have a standard library which makes it easy to integrate into any platform. For example in Windows OS and other Microsoft products you've been able to use JavaScript as a scripting language for a very long time. So JavaScript is not a language that has only been available in browsers. There are actually people out there that prefer JavaScript and write in it voluntarily.
Personally, I'd say Lua and its family of small, easy languages more easily fills those roles.
Not that I doubt some people do voluntarily enjoy JavaScript, but because of the sheer volume of StackOverflow questions, blog posts, micro-techologies, and other assorted attention bestowed upon the language it can be easy to make the logical jump that JavaScript the language is far more popular (in the satisfaction sense) than is actually so.
Right, however javascript will still be the only full featured language having its runtime and libraries included with the browser. That means that for other languages, only the ones with fairly light runtimes and libraries could be suitable for inclusion in most web apps. This will limit the choices for non javascript general development. It may be possible to do a webassembly/webgl rendering engine to replace html/css using a limited set of dependencies.
Most news sources already load between 2 and 10 megabytes of Javascript, which is a significant fraction of, say, Python's runtime and many, many people browse those pages on mobile devices and connections without a problem. In Python's case, a large amount of the runtime size is taken up by all of the platform specific implementations of the standard library and they wouldn't work in the sandbox anyway.
Is there anything preventing Python.org from hosting the runtime environment on their CDN that everyone caches locally? Are there security issues from cross domain modules? Worst case, I don't think it would be hard to extend the LocalStorage API to cache modules between domains (perhaps with signed runtimes and a fallback).
I've been writing JavaScript in a professional context for years, and I have never added an integer to a string. I have never debugged code accidentally doing so, and I've never seen functions written that casually swap between such different return types.
Yet here we are, over and over, reading the obligatory complaint in every JS thread about its type coercion and corner cases. Who are all these programmers who can't go a day without tripping over and subtracting booleans from objects, or multiplying arrays by strings, or dividing functions by nulls? Do they suffer this affliction in other languages too? Do they divide by error codes and subtract function pointers from charcodes?
I mean, I agree with you but that's not even that bad of an example. I would expect many languages to do something similar. Something like this might be a better example:
> I would expect many languages to do something similar.
Of the common dynamic languages I can think of, the only ones that do something similar are Perl/Perl6 and PHP, and even they are still saner than JS.
$ $((1+\2))
bash: 1+\2: syntax error: operand expected (error token is "\2")
$ $((1-\2))
bash: 1-\2: syntax error: operand expected (error token is "\2")
$ ruby -e"1+'2'"
-e:1:in `+': String can't be coerced into Integer (TypeError)
from -e:1:in `<main>'
$ ruby -e"1-'2'"
-e:1:in `-': String can't be coerced into Integer (TypeError)
from -e:1:in `<main>'
$ python3 -c"1+'2'"
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
$ python3 -c"1-'2'"
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'int' and 'str'
>>> exit()
$ python2 -c"1+'2'"
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
$ python2 -c"1-'2'"
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'int' and 'str'
$ perl -e'print 1+"2"."\n"'
3
$ perl -e'print 1-"2"."\n"'
-1
$ perl6 -e"say 1+'2'"
3
$ perl6 -e"say 1-'2'"
-1
$ php -r'echo 1+"2","\n";'
3
$ php -r'echo 1-"2","\n";'
-1
$ racket -e '(+ 1 "2")'
+: contract violation
expected: number?
given: "2"
argument position: 2nd
other arguments...:
1
$ racket -e '(- 1 "2")'
-: contract violation
expected: number?
given: "2"
argument position: 2nd
other arguments...:
1
$ sbcl
This is SBCL 1.3.18, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (+ 1 "2")
debugger invoked on a TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {1001F0EC33}>:
The value
"2"
is not of type
NUMBER
when binding SB-KERNEL::Y
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-KERNEL:TWO-ARG-+ 1 "2") [external]
0] 0
* (- 1 "2")
debugger invoked on a TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {1001F0EC33}>:
The value
"2"
is not of type
NUMBER
when binding SB-KERNEL::Y
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-KERNEL:TWO-ARG-- 1 "2") [external]
0] 0
* (exit)
$ erl
Erlang/OTP 19 [erts-8.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Eshell V8.3 (abort with ^G)
1> 1+"2".
** exception error: an error occurred when evaluating an arithmetic expression
in operator +/2
called as 1 + "2"
2> 1-"2".
** exception error: an error occurred when evaluating an arithmetic expression
in operator -/2
called as 1 - "2"
3> halt().
$ elixir -e '1+"2"'
** (ArithmeticError) bad argument in arithmetic expression
:erlang.+(1, "2")
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/code.ex:170: Code.eval_string/3
$ elixir -e '1-"2"'
** (ArithmeticError) bad argument in arithmetic expression
:erlang.-(1, "2")
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/code.ex:170: Code.eval_string/3
In the awk macro of TXR Lisp, I wanted to provide some of the convenience of the "duck typing" in Awk, whereby a string which looks like a number can be used like one. Instead of supporting such a thing directly (which I consider a computer science flunk job in language design) I came up with a field conversion facility that has a succinct syntax: clear and unobtrusive.
There are more conversion specifiers than just r and i. There can be any number in a row before the first colon, in the middle, or after the last colon. Conversions are matched with fields and applied. If a colon occurs, conversions after the colon are repeatedly applied to the remaining fields in cyclic repetition. If two colons occur, conversions after the second colon are applied to the trailing fields. There is intelligent prioritizing when these rules overlap.
There are conversions with a z suffix which treat junk as zero:
8> (awk (t (fconv : iz) (prinl f)))
a b c 1 2 3
(0 0 0 1 2 3)
Without this, you get nil which will blow up if used as a number -- but you can test for it and handle the situation rather than getting a silent zero:
9> (awk (t (fconv : i) (prinl f)))
a b c 1 2 3
(nil nil nil 1 2 3)
Basically the whole "anything can be used as a number, and junk makes zero" nonsense can be avoided with only a small reduction in code golfing. Textual duck typing is a wrongheaded solution for an ergonomic problem, which sacrifices correctness and clarify of data representation for the sake of absolutely minimizing the program character count.
I think javascript is so popular because it's the only language for browsers. I think if you got better alternatives in the browser then javascript would lose much of it's popularity. It's not going to die overnight but my guess is that it's popularity will decline
I honestly find it a bit crazy that we have webasm before viable multitasking in JavaScript. webworkers being multi-process not multi-threading, and also extremely slow, limited, and needlessly RAM intensive. Multi-process could have worked if they would have at least had fast messaging (~1ms communication overhead is absurd), some form of shared data (at least let me share immutable ArrayBuffers! it's immutable! that's safe!), and some form of move operation instead of copy to allow for cheap handoffs of data structures. That'd still all be safe, no risk of memory corruption, etc...
But no, let's port assembly to the browser instead! Then you get that extra bit out of that one already-overloaded core instead of tapping in to the potentially 15+ other cores on the device!
I'd put forth that that's a far bigger issue to web app performance than HTML/CSS/DOM is. It is for the very heavy web app I've worked on, anyway.
WebAsm's most intriguing aspect as a result is that it has plans to actually add threading along with things like SharedArrayBuffer. That would make locally-intensive & offline webapps vastly more viable.
Javascript is fine, but as you already know, everybody wants to use his/her language of choice. And, more importantly, everybody should be able to choose the right language for the specific task.
What could happen, with WebAssembly, is the opposite: A wane in Javascript's popularity.
What could happen, with WebAssembly, is the opposite: A wane in Javascript's popularity.
If the right moves happen, possible. If the wrong moves happen, it will be the second coming of plugins. Languages based on WebAssembly have to be 1st class citizens in the browser infrastructure, otherwise it will be a repeat. This means that debugging has to be transparent. Access to the DOM has to be ultimately the same.
It doesn't all have to be javascript, HTML and DOM, you know. That's why this is an important step.
Wanna use TurboPascal to write apps, and target the entire known universe of Web browsers? Go right ahead. You can do that now.
Of course, I'm being extreme, but .. you know .. there are other great ways to exploit WebAssembly as a target, and save yourself a huge amount of cultmind headache by avoiding all of the so-called "higher" layers of the stack, completely.
For example, I'm quite happy writing the most cross-platform'est code, in like, ever, using Lua.
And targeting WebAssembly in this circumstance is a no-brainer.
Even web assembly needs to call back to javascript API's to perform webgl interactions. Emscripten provides an easy to use SDL library that makes it a bit less painful. Should be noted that due to security layers there's quite a few webgl, networking and system calls that are not available. In addition good luck getting any threads working, you can fake that out by simply calling them in a setTimeout. In addition its very low level; and if you toss in libraries you'll find your binaries being VERY large.
Well writing in languages for native code is still just as popular, and we're moving in such a direction to allow for the same application to be available both on the web and on your machine. The pure-Javascript approach to offering the same is to package a browser with a web-app and disguise this as a standalone application, which is ass-backwards.
> However, javascript is an increasingly popular language everywhere. I'm not sure people will want to move away from it for most development.
You'd be wrong, many people would love to move away from to something better. There are many better languages than JS and we'd like to not be limited to one shitty quirky hastily designed language in the browser.
I actually went through all the steps of getting rustc and emscripten working, got it set up in Docker. It actually works, I was able to compile a rust program to wasm. But.. because emscripten uses a custom version of LLVM and clang, the image took up 25 GB of my harddrive! I just don't have that kind of space to leave it lying around, so I'll have to wait until they integrate into upstream I guess.
I might work a bit in Rust by itself and compile using emscripten later on the server, but kind of hard to do that if I want to access DOM/canvas/webGL, etc.
I am very excited by this project, it opens up a lot of possibilities. Finally we can use our users' web browsers to the maximum potential, in the language of choice.
Consider: If a good javascript engine like V8 can go as far as being able to emulate hardware, how far can we go with something like webassembly?
I'm sorta afraid of what people will do with wasm. I'm fairly sure 99% of web programmers won't need this but will use it to ship all kinds of stupid garbage that will inevitably wind up executing on some page I'm debugging.
Surprisingly I am struggling to find such essential information as where exactly is wasm supported right now. In latest Chrome? How about Edge? how about the browser on my smartphone?
Why do you want to do that? afict, this shouldn't be increasing the attack surface any more than almost any new language feature. Its spec-ed to run in the same VM as JS is currently.
You are not forced to use C or C++. Rust has automatic memory management via its Ownership System. Once you get used to it, it feels a lot like a garbage collected language.
Maybe https://nim-lang.org would make sense for you? It's GC'd but compiles to C. I've been meaning to try it out and try compiling to WASM when I get a chance.
This brings up a question I've been meaning to ask when the topic came up, because I know almost nothing about GC. How does nim (a GC'd language) compile to a non-GC'd language? And since this is a thing that's possible (unless I'm misunderstanding, which is likely), why does WASM need to add support for GC (http://webassembly.org/docs/gc/#native-gc)?
No, you can write in many other languages. For example there are many compilers out there that will compile <insert your favorite programming language> into LLVM bytecode.
And then you can translate such LLVM bytecode into Webassembly using a tool like Emscripten.
Thus you can compile <insert your favorite programming language> to Webassembly!
It is not C in the browser. It is a sort-of-virtual machine in the browsers.
Browsers (i.e. Chrome) are already doing this to execute Javascript, for example. Webassembly, to put it in a simplified way, allows you to "bypass" the javascript layer and target directly the virtual-machine. And done in a compatible, well-documented way.
You're carting around an entire browser, it's so far from native that it's completely laughable.
As a point of reference:
In 1984:
MacPaint, 5,822 lines of Apple Pascal, 3583 lines of assembly
QuickDraw (dependency): 17,101 lines, all assembly
Compiled Size: 0.05MB
Today, Chrome:
Number of lines of code: 16 MILLION
Webkit (alone): 10.3 MILLION
Install size: ~200MB
We have a bunch of people who aren't skilled enough to deal with a real machine who think they're still "near native". Every single thing won't be as fast, or as small, as the underlying hardware can be using toolkits and platforms that have been available for 20+ years (cross platform toolkits and Java both). For god's sake, Java is a portable VM! wxWidgets is cross-platform, and open source!
We accept an operating system in our way as it is, and now we accept not only an operating system, but an entire browser as well? Our computers are faster than supercomputers used to be - why does Photoshop (or ANY program) take so long to load?
We have to go the other direction - start removing all the garbage from computing, keep the best bits, throw the rest out. If you can't hack on a real computer, that's fine - you have the Webassembly sandbox. But don't label it "near native" - it just shows you don't care enough about computers to read about them. I hear that and it sounds like my gradma talking about computers - that same level of understanding. Nana is amazing, but she's not so great at computers. And these people are supposed to be developers?
Well I'm in favor of things running in a sandbox, especially random code delivered over the internet and run automatically in my browser. But aside from that, WebASM has a flat memory model and (so far) no built-in garbage collection. It has very few features, it's very fast to parse and it runs fast too. Even the asm.js version was fast back in 2013 https://hacks.mozilla.org/2013/12/gap-between-asm-js-and-nat...
As for the rest, I don't know how you're measuring. Photoshop runs a lot faster than programs on my Centris 610 did, and sure it's a bloated mess of different programs glommed together but guess what, it does a lot more than smaller programs do. Your comment counts the cost of everything and the value of nothing. You can't click a link and get a brand-new full-featured word processor running on an old Mac in 10 seconds like you can by clicking https://docs.google.com/ But I can run MacPaint in my browser thanks to asm.js https://archive.org/details/mac_MacOS_7.0.1_compilation
https://xkcd.com/1367/ I don't think I understand your comment about attack surface. A Chrome sandbox is a lot harder to attack than a Mac Classic installation - or pretty much any current method of "native" installation.
I totally agree. However, it is to be expected, when we first abstract up to get convenience and then using that platform, abstract back down to get performance.
We end up with a FrankenMonster of an application, that has a cobbled together persona, built by people who do not appreciate what the machine is actually doing.
This can probably only be expected to get better and better. While JS engines are squeezing hard to get some extra performance, WASM is just beginning its life.
It'd be great if someone would make (when it's technological feasible) a way to integrate this natively in node, something like:
const wasm = require('wasm-native');
(async () => {
const mymodule = await wasm('mymodule.c');
// use mymodule here
- WASM is platform independent, so it can easily be precompiled. Which means just the .wasm module needs to be distributed (e.g. inside a npm package). However WASM modules only have access to things that were already available to JS before (no random C/C++ libraries can be included which e.g. call into the OS, no multithreading, etc.). And the toolchain might be at the moment not yet the easiest to set up.
- Node native extensions have quite good tooling support. Write a binding.gyp and the C++ files and everything works pretty smooth. The native code can also do everything that native code is allowed to do on the platform. However node native extensions are platform specific, which means either precompile them for all target plattforms (and each node release) or deliver C/C++ sources which are always compiled on the deployment plattform at npm install time. They also can't be shared between browser and node plattform.
All in all I think they have slightly different usecases:
- Node native extensions for accessing operating system APIs and other libraries which are not already exposed through nodes JS APIs.
- WASM for making existing C/C++ code including full applications (like games) runnable in the browser
- WASM for making modules which speed up pure algorithms (like audio processing) and which can be used on both platforms.
You can play my favorite arcade game ever in a wasm gameboy emulator (credit goes to Ben Smith of Google: https://github.com/binji/binjgb) in a web-based OS I've been working on for 5 years. This is known to work in current Chrome and Firefox. Keyboard game controls: 'w'=up 'a'=left 's'=down 'd'=right '.'=A ','=B space=start enter=select. Also, standard (17 button, 4 axis) USB gamepads should "just work" via plug'n'play.
The argument in the URL is the base64 encoding of an initialization script that is being passed to the desktop environment. Going to the link in current Edge should just open the "Arcade" app, with nothing else happening.
You should be able to drag-n-drop ".gb" or ".nes" ROM game files from your native desktop right onto the Arcade app window, and it should just start playing. You can also just drop them onto the web desktop to save them there, then just double-click them when you want to play. That way, the file is kept in the site's local storage.
Also keep an eye on https://github.com/dcodeIO/AssemblyScript :)