Fixed localStorage availability test (for real this time), and asynchronified embed.js

I spent some time fixing the latter because browsers have started warning that synchronous XMLHttpRequest calls on the "main thread" (as Firefox calls it) are deprecated. Since the days of such calls seems to be numbered, I decided to act sooner rather than later.  All PCjs XMLHttpRequests go through a single library function (weblib.loadResource), which accepts an fAsync parameter, and the only code that is still allowed to pass false for that parameter are "emergency" shutdown requests (which I believe browsers must still allow).
This commit is contained in:
Jeff Parsons 2014-10-28 17:12:24 -07:00 committed by jeffpar
commit e0487bccd8
9 changed files with 1397 additions and 1245 deletions

View file

@ -1,7 +1,6 @@
JavaScript Negativity
---
For those of us coming from the world of C, it's easy to be "negative" about the way JavaScript deals with 32-bit
integers.
Coming from the C programming language, it's easy to be "negative" about how JavaScript deals with 32-bit integers.
As a newcomer, you quickly learn that JavaScript supports only one numeric data type -- 64-bit floats -- and you groan.
@ -9,9 +8,9 @@ Then you learn that all the "bitwise" operators (**~**, **|**, **&**, **^**, **&
**>>>**) treat their operands as 32-bit integer values and produce 32-bit integer results, and you breathe
a sigh of relief.
But then you start noticing oddities. In 32-bit C programming, you can take any 32-bit value,
such as -1526726656 (which is equivalent to 0xA5000000), mask it with 0x80808080, and get 0x80000000. However,
in JavaScript, you actually get -0x80000000, which, sadly, is not equal to 0x80000000.
But then you start noticing oddities. In C, you can take any 32-bit value, such as -1526726656 (which is equivalent
to 0xA5000000), mask it with 0x80808080, and get 0x80000000. However, in JavaScript, you actually get -0x80000000,
which, sadly, is not equal to 0x80000000.
To verify, type the following into any JavaScript REPL (eg, Node):
@ -22,28 +21,28 @@ To verify, type the following into any JavaScript REPL (eg, Node):
> n.toString(16)
'-80000000'
So the notion that bitwise operators yield 32-bit results isn't exactly right; every result continues to be
sign-extended into the entire 52 "significand" bits of the underlying 64-bit float. And it's impossible to simply
"mask away" those unwanted sign bits, thanks to the fundamental restriction of JavaScript bitwise operators:
they operate *only* on the low 32 bits.
So the notion that bitwise operators yield 32-bit results isn't exactly right; the sign (bit 31) of every 32-bit
result is always extended into the entire 52 "significand" bits of the underlying 64-bit float. And it's
impossible to simply "mask away" those additional sign bits, thanks to the fundamental restriction of JavaScript bitwise
operators: they operate *only* on the low 32 bits.
If you really want 0x80000000 instead of -0x80000000, add 0x100000000:
The easiest way to remove the high-order sign bits from a negative 32-bit value is to add 0x100000000:
> n = (n < 0? n + 0x100000000 : n)
2147483648
> n.toString(16)
'80000000'
This works because JavaScript is perfectly capable of representing 0x80000000 as a positive number.
But be careful, because as soon as you perform *any* bitwise operation on a value with bit 31 set, even
something as innocuous-looking as:
This works because JavaScript is perfectly capable of representing 0x80000000, or any other 32-bit value, as a positive
number. But be careful, because as soon as you perform *any* bitwise operation on a value with bit 31 set, even
an operation as innocuous-looking as:
> n |= 0
-2147483648
> n.toString(16)
'-80000000'
Viola: instant negative number! To continue the fun, now "or" a one into bit 0:
Viola: instant negative number! To continue the fun, now "or" one into bit 0:
> n |= 1
-2147483647
@ -53,7 +52,7 @@ Viola: instant negative number! To continue the fun, now "or" a one into bit 0:
Viola: all low 32 bits have instantly flipped!
Actually, no, this time, I'm pulling your leg. The low 32 bits of the internal value are exactly what you would
expect: 0x80000001 (the internal representation would look more like 0xFFFFF80000001). The toString() method is
expect: 0x80000001 (the internal representation looks more like 0xFFFFF80000001). The toString() method is
just a little misleading. As the MDN docs explain, for a negative number, toString() returns the positive
representation of the number, preceded by a - sign, *not* the "two's complement" of the number.