LABjs, a JavaScript library for
loading JavaScript libraries, relied on one of two behaviours to
implement its asynchronous loading behaviour:
The browser executing dynamically-inserted scripts in insertion
order, even if a later-inserted-script finished downloading before an
earlier-inserted one. (Firefox and Opera did this.)
The browser downloading scripts declared in a script
element's src attribute even if the type
attribute had some value that meant the script would not get
executed. (WebKit and IE did this.)
It would use the first behaviour if the browser implemented the
MozAppearance property in the CSSOM (a Mozilla extension)
or if the browser had an opera property, and it would use
the second behaviour otherwise.
Unfortunately, neither of these behaviours were defined:
historically, the HTML spec has been incredibly vague about what order
dynamically-inserted scripts should execute in and when to download
scripts. This is why the browsers didn't all do the same thing.
With the WHATWG effort, we try to pin all these behaviours down so
that browsers can converge on one set of behaviours and Web developers
don't have to worry about sniffing to use different behaviours in
different browsers, like LABjs does.
When browsers don't have good interoperability, we usually pick the
saner behaviour. In this case, that meant not downloading scripts that
wouldn't execute anyway, and not applying a strict execution order on
scripts that get inserted into the document dynamically. Both of these
decisions are intended to improve performance.
Over time, browsers converged on these behaviours. First, Gecko
removed the ordering on dynamic scripts. This broke LABjs. Arnout
Kazemier was first to
report the breakage in Firefox nightly builds. Kyle Simpson, who
works on LABjs, posted
about the issue on the Getify blog. A Mozilla evangelist noticed
and pointed the situation out to Henri Sivonen, who subsequently started
a public-html thread to discuss possible solutions; discussion
later migrated to a
WHATWG wiki page.
Thankfully, Henri was able to coordinate with Kyle and other Web
developers, as well as with the other browser vendors, to come up
with a
solution (mostly based on Kyle's suggestions), which he documented in
detail (See also: Mozilla
bug, WebKit
bug).
In the near future, WebKit builds will likely
stop downloading scripts that it isn't going to execute (this has
already changed for parser-inserted elements, but script-inserted
elements haven't yet had this change applied). I've updated
the HTML spec with the above proposal, so they'll likely implement
that too.
The solution is basically to add a magic flag which can be reset
from script. The flag is only set on script elements
created from script, and causes the browser to assume that the
async attribute is set. If you reset this flag (by
setting script.async = false in script) then
the attribute is honoured.
I must admit to not being a huge fan of the solution. Magic like that is highly unintuitive. However, in this particular instance Henri took the lead and got the key stakeholders of the moment on board, and that often has more weight than getting a perfect solution.
David Baron has proposed a possible solution for the :link/:visited privacy problem. I've changed Acid3 so that it won't fail if you implement his proposal. The following is the diff:
--- index.html.prev 2009-08-14 00:00:00.000000000 +0000
+++ index.html 2010-04-02 20:13:49.000000000 +0000
@@ -129,8 +129,12 @@
/* rules specific to the tests below */
#instructions:last-child { white-space: pre-wrap; white-space: x-bogus; }
- #linktest:link { display: block; color: red; text-align: center; text-decoration: none; }
- #linktest.pending, #linktest:visited { display: none; }
+ /* replaced for http://dbaron.org/mozilla/visited-privacy with the three rules after it:
+ #linktest:link { display: block; color: red; text-align: center; text-decoration: none; }
+ #linktest.pending, #linktest:visited { display: none; } */
+ #linktest { position: absolute; left: 17px; top: 18px; color: red; width: 80px; text-decoration: none; font: 900 small-caps 10px sans-serif; }
+ #linktest:link { color: red; }
+ #linktest.pending, #linktest:visited { color: white; }
#\ { color: transparent; color: hsla(0, 0, 0, 1); position: fixed; top: 10px; left: 10px; font: 40px Arial, sans-serif; }
#\ #result, #\ #score { position: fixed; top: 10%; left: 10%; width: 4em; z-index: 1; color: yellow; font-size: 50px; background: fuchsia; border: solid 1em purple; }
</style>
@@ -1869,7 +1873,7 @@
var iframe = document.getElementById("selectors");
var number = (new Date()).valueOf();
var a = document.createElement('a');
- a.appendChild(document.createTextNode('LINKTEST FAILED'));
+ a.appendChild(document.createTextNode('YOU SHOULD NOT SEE THIS AT ALL')); // changed text when fixing http://dbaron.org/mozilla/visited-privacy
a.setAttribute('id', 'linktest');
a.setAttribute('class', 'pending');
a.setAttribute('href', iframe.getAttribute('src') + "?" + number);
@@ -3106,23 +3110,25 @@
},
function () {
// test 80: remove the iframes and the object
+ // (when fixing the test for http://dbaron.org/mozilla/visited-privacy,
+ // this section was flipped around so the linktest check is done first;
+ // this is to prevent the 'retry' from failing the second time since by
+ // then the kungFuDeathGrip has been nullified, if we do it first)
+ // first, check that the linktest is loaded
+ var a = document.links[1];
+ assert(!(a == null), "linktest was null");
+ assert(a.textContent == "YOU SHOULD NOT SEE THIS AT ALL", "linktest link couldn't be found"); // changed text when fixing http://dbaron.org/mozilla/visited-privacy
+ if (a.hasAttribute('class'))
+ return "retry"; // linktest onload didn't fire -- could be a networking issue, check that first
assert(!(kungFuDeathGrip == null), "kungFuDeathGrip was null");
assert(!(kungFuDeathGrip.parentNode == null), "kungFuDeathGrip.parentNode was null");
+ // ok, now remove the iframes
kungFuDeathGrip.parentNode.removeChild(kungFuDeathGrip);
kungFuDeathGrip = null;
// check that the xhtml files worked right
assert(notifications['xhtml.1'], "Script in XHTML didn't execute");
assert(!notifications['xhtml.2'], "XML well-formedness error didn't stop script from executing");
assert(!notifications['xhtml.3'], "Script executed despite having wrong namespace");
- // while we're at it, check that the linktest is loaded
- // since the other iframes have forcibly loaded by now, we assume that
- // there's no way this can't have loaded by now
- // (probably a safe bet)
- var a = document.links[1];
- assert(!(a == null), "linktest was null");
- assert(a.textContent == "LINKTEST FAILED", "linktest link couldn't be found");
- if (a.hasAttribute('class'))
- return "retry"; // linktest onload didn't fire -- could be a networking issue, check that first
return 5;
},
Adobe CEO Shantanu Narayen, June 2009, when asked about HTML5: To the extent that an improved HTML standard accelerates innovation and consistent reach for web content, we’re very supportive. (context)
Adobe CTO Kevin Lynch, February 2010: Adobe supports HTML and its evolution. (context)
Adobe Evangelist Dave McCallister, July 2009: For Adobe, "open" is all aspects of communications and technologies. For us, those are open source, standards, and community. [...] We make sure that we talk to our communities, that we play with the standards groups, [...] We are actually one of the most open companies that are active. (context)
Someone whom I can't identify publicly, since he posted only on one of the secret W3C member lists, contributed to the following thread over the last few days:
123
Net result: the latest publication of HTML5 is now blocked by Adobe, via an objection that has still not been made public (despite yesterday's promise to make it so).
For reasons that aren't material to this rant, I'm trying to get a
T-Mobile SIM card set up with T-Mobile's ridiculously named "Even More
Plus 500 Talk + Text + Web" plan. At this point I have a SIM card, and
after much pain and suffering in phone conversations and online chat
support, I have an account that is fully paid up.
Let's log in to the "My T-Mobile" site's "Billing & Payments" page
to see how much I currenly owe:
Ok it says I owe $62.42 by 1/19/2010 (today) for service from
2/9/2010 - 3/8/2010 (next month). But it also says that my monthly
charges for my previous bill are $127.42 due on 3/9/2010
(two months from now).
None of those numbers seem to add up to $59.99, which is what the
"Even More Plus 500 Talk + Text + Web" plan is advertised as costing,
but I suppose $62.42 could equal $59.99 if one were to imagine that
T-Mobile felt they could put a few "fees" on there that for whatever
reason could be assumed not to count. But what's with the $127.42? And
what's with the due dates? Let's click "See details" to see
details:
Wait, bill summary? I wanted details! And hold on, this page says
my account balance is $0.00, and that I paid $62.42 on 1/20/10
(tomorrow). It also gives my monthly charges twice... once as $0.00,
and once as $127.42! I guess if you average them it adds up to $63.71,
which is similar to $62.42...
Oh look, the details are below the fold.
This says the next service period is $63.71, that they've received
$62.42, that the previous balance was $63.71, and that they "adjusted"
my account by $65.00 (the result of my calling billing support because
they hadn't applied the $63.71 they actually charged me to my
account), and apparently that all adds up to me owing $0.00... by
02/05/2010.
Clearly maths is not their strong point. Also not their strong
point: being consistent about how they mark up dates. Or how they
decide what dates are important.
Oh and... also not their strong point: matching reality. So far
they've only actually charged me $63.71, once, though I have in fact
tried to pay more than once (earlier today I also tried to pay the
$62.42 that some of these pages claim I owe, though my bank has yet to
see that charge).
Still, the $127.42 is a bit confusing. Let's see what the "View
Bill" button under that number brings up.
Whaaaa!? FPEvenMorePlus 500TTW $119.98? What on earth is that?
"Amount due 2/05/10: $127.42"? That completely contradicts the
previous page! How much do I owe on that day, $0, or $127.42??
They say the way to work out how much you owe is to dial #225# from
the phone, so let's try that... Ok, that says $0. I guess the phone
would know best.
I give up trying to work out how much I owe; let's instead try to
get the "Unlimited Data" working on this phone. I've heard rumours
that one has to buy a $0 optional extra "Unlimited Web" service since
otherwise the "Even More Plus Unlimited Web" is actually limited. Add
additional services on this line... Internet & E-mail... Aha, here
we go. "T-Mobile Smartphone Unlimited Web with FlexPay". That sounds
promising. And it's free! Just like the rumours. Let's "buy" that and
quickly review the charges:
Added plan and services... $0, yup. Unchanged plan and
services... $59.99. Yup. So, the grand total is... $89.99. Wait, wait,
hold on, let me recheck the maths here... $0... plus $59.99... carry
the one... What??
Ok, ok, clearly it got confused. Let's close the browser and start
over. Add additional services on this line... Internet &
E-mail... "T-Mobile Smartphone Unlimited Web with FlexPay". And it
says FREE. So we click it again, and let's see how much $59.99 + FREE
equals this time:
TEN THOUSAND AND EIGHTY EIGHT DOLLARS AND NINETY NINE CENTS?!
I'm on hold with T-Mobile. The guy is very nice, but there's so much interference I can barely hear what he's saying half the time. Something about me having to pay a month in advance instead of at the end of the month (which I prefer anyway), and something about the order not going through for "reasons unknown" though he has already done "the credit check". Beats me why a credit check is necessary if I'm paying in advance without a contract, by the way, but that's another story. Same thing happened when I paid cash to buy a car recently. "We need to run a credit check". You knock yourself out.
Why can't all this stuff be done by e-mail? Really? I hate phones.
Time passes.
Hey check this out. The support guy gave up, and now I'm doing this all over again with sales! At least the connection is clearer now. Ok so I want the $59.99 plan, which of course comes with a $1.21 non-tax non-government "regulatory" fee and a $35 "activation" fee (given how hard this has been so far, I understand charging an activation fee, though I wonder if we could come to some arrangement wherein I get paid for my part in this ordeal also).
"Sir, what is your phone number?" Well, I don't know, aren't you supposed to tell me that? I mean, I don't have a phone, that's why I'm buying a phone. After trying to explain that I just gave them my Google Voice number — it's not connected to anything but at least they can leave me voicemail, I guess.
Ok, now we have to go through the terms of service... don't forget to opt out of the "you can't use the legal system if we screw you over" option.
"Actually sir, you can't have Flex Pay, you have to have Take Control." I have no idea what that sentence means. I wasn't aware I was trying to get either of those. What are you talking about. "Um..." time passes again "Ok it's going to be $59.99 plus $1.25 tax" (it's not a tax, that's a lie, but we'll let that slide) "so that's a total of $70." I'm going to briefly ignore the fact that those numbers don't add up, and ask where the activation fee went.
"Um... there's no activation fee with this plan."
"It's still the 500-minute, unlimited web, unlimited sms plan?"
"Sure."
"And how do I transfer an existing number to this SIM card?"
"Oh, uh, call technical support when you've received the SIM card. Yeah. We can't do that now but we can do that once we've taken your money, I'm sure."