Mozilla 2

Mozilla has gone from open source whipping boy in 1999 to open source poster child since 2004, due in large part to the success of Firefox. For that we can thank some amount of luck with our “timing the market” — the browser market that no one knew existed, until it was suddenly clear in the summer of 2004 that Microsoft had dropped the ball and Firefox was picking it up.

But we didn’t just get lucky. Putting the regular user first with Firefox’s default UI and interaction design, building on real-world web standards instead of start-from-zero fantasy web standards, persevering against bug adversity over time, and calculated (but secondary — the apps came first) work on “the platform”, especially to aid web developers and power users via add-ons, were all necessary to our success.

In particular, Firefox couldn’t have happened without Mozilla 1.0, a release milestone about which I wrote a requirements manifesto in early 2001. Mozilla 1.0 came out in June of 2002, and finally won back reputation lost due to Netscape 6 and the big rewrite. It set the stage for Firefox, Thunderbird, and other XUL applications.

For Mozilla 1.0, the architectural die was cast in late 1998 and 1999, so the process to reach 1.0, with its stable set of APIs on which most of a browser could be built, consisted mainly of the hard work of finishing. Since then, much of the code base has been revised in some way, but always incrementally. No “big bangs.”

The current CVS trunk, which will become the Mozilla 1.9 stable branch some time in the first half of next year, contains significant rendering rearchitecture, along with lots of other important work I won’t go into right now. The graphics work and the reflow refactoring are perhaps the most aggressive changes conceivable in the Mozilla milestone process. That process, more or less still the same as described in the “mozilla 1.0 manifesto”, depends crucially on community QA and patch contributions, which must converge on a product alpha/beta/release cycle to have enough real-world testing to claim meaningful code coverage. This cycle continues in 1.9, on which Firefox 3 will be based.


So Mozilla is a large, mature, fairly conservatively maintained open source code base. What else is new?

Lots: the web as a system of interoperating and open standards is under renewed assault. Browser competition is heating up, which is great except where it portends innovations locked into proprietary stacks. The mobile device space is growing dramatically, yet with power storage and dissipation limits temporarily repealing Moore’s Law. Worse, carriers and handset makers control all software most users get, leaving little room for the kind of choice that led to Firefox. Let’s save the mobile thought for another time.

What about desktop systems? In four years, desktops will have polycore CPUs, with (still specialized but increasingly useful) teraflops in the GPU. Multimedia and 3D content will become more tractable by mere mortals without expensive, complicated tools, or there will be a lot of wasted power and bandwidth. Never mind 3D — just better search, better text rendering, usable video, and all kinds of user-oriented optimization tasks should soak up those hardware threads’ cycles. Whatever happens, it seems a shame to leave all that capacity to games, other proprietary software, and closed content formats.

So what should we do in Mozilla-land about this?

First, we should do Mozilla 2, targeting 2008, “after” Mozilla 1.9 — but we should start working on it very soon, next month. We should not follow 1.9 with 1.10 and run headlong into the law of diminishing returns. Second, after Mozilla 2 is well under way, we will worry about those super-duper CPUs and GPUs. I have some thoughts, but I’ll save them for another post.

Mozilla 2 means among other things a chance to break frozen API compatibility, which removes constraints on the current architecture and allows us to eliminate old APIs and their implementations, renew and improve the APIs and code we want to keep, and realize significant runtime and code size wins. For instance, we can get rid of RDF, which seems to be the main source of “Mozilla ugliness” humorously decried by Steve Yegge.

For Mozilla 2, we will have a JIT-oriented JavaScript VM (details soon) that supports the forthcoming ECMAScript Edition 4 (“JS2”) language. Among the desirable characteristics of this VM will be a conservative, incremental garbage collector (GC). If it makes sense, we can use this GC module to manage DOM object memory instead of using XPCOM reference counting. We can use its conservative scanning code to assist in cycle collection. And we can JIT calls directly into DOM glue code entry points (provided no JS mutation has overridden a method property value), bypassing the powerful but relatively slow typelib-based dispatching machinery of XPConnect.
This will kick Ajax performance in Firefox up a notch or three.


This is just a start.

For Mozilla 2, because we can break API compatibility where it makes sense to do so, we can and will provide better APIs, “on the outside” of Gecko — and remove XPCOM API boilerplate “on the inside”. We can translate old C++ portability veneer into standard C++ where doing so does not cost us portability, performance, or correctness. We can even switch to C++ exceptions if doing so wins in both code size and runtime performance in a fair contest.

So instead of code like this:

PRBool
nsXULDocument::OnDocumentParserError()
{
// don't report errors that are from overlays
if (mCurrentPrototype && mMasterPrototype != mCurrentPrototype) {
nsCOMPtr<nsIURI> uri;
nsresult rv = mCurrentPrototype->GetURI(getter_AddRefs(uri));
if (NS_SUCCEEDED(rv)) {
PRBool isChrome = IsChromeURI(uri);
if (isChrome) {
nsCOMPtr os(
do_GetService("@mozilla.org/observer-service;1"));
if (os)
os->NotifyObservers(uri, "xul-overlay-parsererror",
EmptyString().get());
}
}
return PR_FALSE;
}
return PR_TRUE;
}

you’ll see code like this:

bool
XULDocument::OnDocumentParserError()
{
// don't report errors that are from overlays
if (mCurrentPrototype && mMasterPrototype != mCurrentPrototype) {
IURI *uri = mCurrentPrototype->GetURI();
if (IsChromeURI(uri)) {
GetObserverService()->NotifyObservers(uri, "xul-overlay-parsererror");
}
return false;
}
return true;
}

(I’ve taken the liberty of supposing that we can lose the ns prefix from interfaces in Mozilla 2’s C++ bindings, using a proper C++ namespace [not shown] instead.) I should add that we will not break API compatibility gratuitously; some of our APIs are fine, thank you. “No big rewrites” in the sense that Joel writes about (throw it all away and start over). And much implementation code will be kept, but transformed.

Now, we can’t hope to achieve these code transformations by hand. For one thing, much of our code is not exception-safe. This is where Oink comes in. It would take an army of OCD-savants typing at 120wpm a long time to convert all of Mozilla’s hand-crafted allocate/free and lock/unlock code patterns to RAII, but with help from Oink’s front end Elsa, we can automate the task of rewriting the source. And (with some flow-sensitive work on the Oink side) we should be able to check that we’ve converted every last exception-unsafe case to use RAII.


Oink, or really its friend Cqual, is also good for more involved static code analysis than finding patterns to rewrite and ensuring exception safety. With the right qualifiers, we can enforce higher level safety properties such as “no format string comes from the network”, or “chrome (UI) code must sanitize content data that flows into it”.

I think we should extend the Oink framework to include JS2 in the analysis, for total data flow. With the type system for JS2, we’ll finally have type soundness on which to build higher-level model checkers.

Building this Oink-based tooling won’t be done in a day, and we should be careful not to overinvest if simpler techniques suffice. But from what Roc, Graydon and I have seen, Oink looks quite promising. So Mozilla 2 is not just about simplifying APIs, removing old code and XPCOM overhead, and making the source code more approachable. It’s also about material improvements to program security, which is inherently weak in all browsers implemented in languages such as C and C++. Security requires defense at every level of abstraction, from high-level JS that enforces confidentiality properties, down to buffer manipulations that should be provably memory-safe.

There is no silver bullet. Virtual machines are, as Michael Franz and others point out, a great way to reduce the size of one’s TCB and track information flow, supporting richer security models and policies — safe “mashups in the browser”.

We will optimize the JS2 VM aggressively in the Mozilla 2 timeframe. But we can’t switch to “managed C++” (neither can Microsoft, notice) for any near term competitive browser, nor is JS2 the right language for the low-level systems programming that lies on critical rendering and interaction paths in any browser.

We will combine approaches, moving as much “middleware” C++ as we can, when it’s not on any critical path and it uses only safe pointers, into JS2. Again Oink/Elsa can help to automate this translation. I envision a checker that first scores all code against a series of costs of translating from C++ to JS2, identifying the low-hanging fruit statically. Profiling results for common user-level tasks and page load tests should be used to veto any low-cost judgments that might translate C++ that’s otherwise ripe for JS2, but that actually ends up dominating a critical path.

Whether we invest in C++ to JS2 automation, do it by hand, or use a hybrid of Oink-based and by-hand techniques, I don’t want to decide right now. But as with deCOMtamination, we have an opportunity to work smarter by investing in tools instead of spending programmer talent in repetitive and mostly menial labor on a very large scale. The C++ that we can’t move to JS2 can still be made more secure by combining the other key Mozilla 2 levers: conservative GC (which removes free memory read hazards), Oink-based checkers (with appropriate new qualifiers annotating our source), and dynamic 24-by-7 valgrind plus gcov tinderboxes running automated tests.

Finally, we will run at reduced privilege when we can, and otherwise use OS-enforced security mechanisms that are sound and well-documented. We should put most plugins out of process while we’re at it.


I haven’t really begun to talk about further graphics work (3D canvas) and security models (those safe browser-based mashups). Nor have I begun to discuss Firefox 4, the likely version to be based on Mozilla 2, except to say that we will keep an unbranded Firefox version building at all times as Mozilla 2 is developed. Mainly I am focusing on the Mozilla platform, on which Firefox, its add-ons, and other apps all stand or fall.

So the goals for Mozilla 2 are:

  • Clean up our APIs to be fewer, better, and “on the outside.”
  • Simplify the Mozilla codebase to make it smaller, faster, and easier to approach and maintain.
  • Take advantage of standard language features and fast paths instead of XPCOM and ad hoc code.
  • Optimization including JIT compilation for JS2 with very fast DOM access and low memory costs.
  • Tool-time and runtime enforcement of important safety properties.

Oh, and isn’t it time that we get off of CVS? The best way to do that without throwing 1.9 into an uproar is to develop Mozilla 2 using a new Version Control System (VCS) that can merge with CVS (since we will want to track changes to files not being revamped at first, or at all; and we’ll probably find bugs whose fixes should flow back into 1.9). The problem with VCSes is that there are too many to choose from now. Nevertheless, looking for mostly green columns in that chart should help us make a quick decision. We don’t need “the best” or the “newest”, but we do need better merging, branching, and renaming support.

Last point: much of what I wrote here, much of my work in Mozilla, is focused on the platform, yet I noted above that we always put apps such as Firefox first, and do not claim to be “a platform” for everyone. In spite of this, people are building apps such as Songbird on top of XULRunner.
So what are we, platform or app? The answer is “both, in a virtuous cycle”. Because we serve users first and most broadly, but also developers at several layers — Web, XUL, C++ — we have both undersold and under-invested in the C++ layer. In the long run, neglecting the C++ codebase puts the app at risk. So with Mozilla 2, we’re going to balance the books.

This is enough for now; detailed roadmap and wiki work will follow. I’m intent on moving the Mozilla codebase to a true next level: cleaner, leaner, safer, with better APIs and C++ bindings, and very fast page-load and DOM performance. While this is easier said than done, it is palpably within our reach for 2008. Let’s do it.

Python and JavaScript

Mark Hammond’s work to support Python in XUL is nearly done. The DOM_AGNOSTIC2_BRANCH should land in the next few weeks. Already I see many on the PyXPCOM list testing Mark’s fine work, chomping at the bit to use Python in XULRunner.

This brings to mind a hot topic in my recent hacking: infusing JS with Pythonic generators and iterators, including array comprehensions. Brief taste:

js> function count(n) {
for (var i = 0; i < n; i++)
yield i;
}
js> g = count(10)
[object Generator]
js> g.next()
0js> g.next()
1
js> two_to_nine = [i for i in g]
2,3,4,5,6,7,8,9
js> squares_to_20 = [i * i for i in count(20)]
0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361

Why borrow from Python for iteration, generators, and comprehensions? I typed this into a wiki recently:

Given the years of development in Python and similarities to ECMAScript in application domains and programmer communities, we would rather follow than lead. By standing on Python

Fresh XPCOM thinking

Everyone who gets far enough into Mozilla code has that “wow, this is chatty . . . verbose . . . inefficient even” reaction to XPCOM — or so I thought. Having played Cassandra once in the dark days before Netscape 6, lived to witness deCOMtamination, and watched the next generation of core hackers grow up wise from birth, I foolishly believed that we were well past worrying about XPCOM abuse.

But we aren’t. Perhaps SVG-the-standard is to blame, but not exclusively. We have to do better, and not just with peer pressure, but I’ll spend a paragraph on exhortation too:

Please don’t imitate COMtaminated code. Don’t use XPCOM in core rendering and layout data structures. Do use XPCOM where it wins, as high-level inter-library and inter-programming-language glue, where the QueryInterface and virtual method call costs are noise, and the benefits for programming in the large are obvious.

More than warning again, I believe it is time to change XPCOM in deeper ways, to fix several problems:

  1. The inability to free cyclic structures automatically.
  2. The code bloat and cycle costs of nsresult return type.
  3. The lack of nsIClassInfo implementation.

Problem 1 means memory leaks, forever, because we’ll never cover all cases, and new cases are being added constantly (sometimes just with JS completing the cycle, no C++ changes — so via a Firefox extension, for example).

Problem 2 makes our source code overlarge and hard to read, never mind the terrible effects on register pressure, instruction cache utilization, memory bandwidth wasted on the out param that wants to be the return value, etc.

Problem 3 means we can’t readily reflect on instance-of relationships in JS except for DOM objects. Having DOM class information (what interfaces does this object implement? is this object thread-safe?) is cool, but we still don’t take advantage of nsIClassInfo (e.g. for the solution to problem 1 suggested below) for want of ubiquity. (Another example: we believe we could use it to avoid all locking costs in XPConnect.)

These problems can be solved:

  1. I pointed dbaron and graydon at work by David Bacon et al. on reference-count cycle collecting that we could infuse into XPCOM, curing all cycle-induced leaks. We may hope to have fixed the last such leak, but Murphy was an optimist. XPCOM without some kind of cycle collector is like a car without a brake.
  2. I’m looking for volunteers to help run some experiments testing the state of C++ exception support on the compilers we care about (mainly GCC and MSVC). What is the code size increase from turning on exceptions (rtti too if required)? That’s the first experiment to run. Actually converting our mega-lines of C++ code to use exception handling instead of nsresult returning and testing will be real work, and lots of it. I have some thoughts for how to semi- or fully-automate that work that I’ll blog about soon.
  3. Right now the way you implement nsIClassInfo involves painful C macros, so no one does it. With some C++ sugar, and with the right defaults, defining class information for each concrete XPCOM class should be simple, so we can actually count on it being there.

These problems should be solved, and I’m committed to working to solve them. Who is with me?

JS2 Design Notes

Goals

Here are some design notes for JS2, starting with my goals, shared in large part by ECMA TG1 for ECMA-262 Edition 4:

  1. Support programming in the large with stronger types and naming.
  2. Enable bootstrapping, self-hosting, and reflection.
  3. Backward compatibility apart from a few simplifying changes.

(Goal 2 implies many things beyond what is discussed in these notes.) Non-goals, again shared (mostly!) by ECMA TG1 going back to Waldemar’s Edition 4 drafts:

  1. To become more like any other language (including Java!).
  2. To be more easily optimized than the current language.

Types

In JS today, every expression has a type, as specified by ECMA-262 Edition 3
Chapter 8. The visible types, by their spec names, are Undefined, Null, Boolean, Number, String, and Object. These types are disjoint sets of values:

Undefined = {undefined}, Null = {null}, etc.
Int32 and UInt32 are subsets of Number (IEEE-754 double precision) subject to
different operators from Number, and they appear only in the bitwise operators,
Array length, and a few other special cases.

Edition 3 Chapter 9 defines somewhat ad-hoc, mostly useful conversion rules between types. Chapter 15 contains constructor specifications that may also convert according to the Chapter 9 rules, or ad-hoc variations on those rules.

One oddness to JS1: the so-called primitive types Boolean, Number, and String each have a corresponding Object subtype: Boolean, Number, and String respectively. When a primitive value is used as an object, it is automatically “boxed” or wrapped by a new instance of the corresponding object subtype. When used in an appropriate primitive type context, the box/wrapper converts back to the primitive value.

For JS2 and ECMA-262 Edition 4, we would like to use modern type theory to avoid the pitfalls and contradictions of less formal, ad-hoc approaches. We define a lattice of all type value sets induced by the set contains
subset
relation, in order to:

  1. Define new operators to enable programmers to test and enforce invariants using type annotations (goal 1).
  2. Let users define their own types by writing class extensions that can do anything the native classes can do (goal 2).
  3. Eliminate primitive types and boxing, coalescing each Edition 3 primitive type with its object wrapper (simplifying exception from goal 3).
  4. Provide nullability and rationalize Undefined (goals 1 and 3).

The lattice is as follows, with arcs directed downward by default (arcs directed otherwise have an arrowhead showing direction):

___⊤___
/       
/         
Void        Object?__________
/               
/                 
Null<----String?    Object__________
     /   |           
   /    |            
String  Number  Boolean  User...
(double)
/  |  
/   |   
int  uint  ...

⊤ is the top type, not named T in the language. Edition 3’s Undefined is renamed to Void, as in Waldemar’s Edition 4 drafts.

For all object types t, there exists a nullable type t? = t ∪ Null. Only Object? and String? are shown above, but every object subtype is nullable. Note that this is just a specification notation; we have not committed to adding the ? typename suffix for nullability to the language.

The User… type stands for a hedge of user-defined type trees. I’ve left out Array, RegExp, Date, etc., because they can be thought of as
user-defined Object subtypes. Also, not all proposed numeric types are shown (not all are subtypes of IEEE double).

Type operators

Given a value and a type, you can ask whether the value is a member of the type’s set using the is relational operator:

v is t ≡ v ∈ t's value set ⇒ Boolean

A class defines an object type, and class C extends B {...} defines a subclass C of base class B. All values of a subclass type are members of its superclass type, so (new C is B).

Given a value of unknown type, the as relational operator coerces (or downcasts) the value to the type, resulting in null if the value is not a member of the type:

v as t ≡ (v is t ? v : null) ⇒ t?

So, e.g., undefined as Object === null — this shows how the type of an as t expression is t?.

Given a value of arbitrary type, the to relational operator converts the value to be a member of the nullable extension type, or throws a TypeError exception.

v to t ≡ (v is t ? v : v converted to t) ⇒ t? or throw TypeError

The to operator may result in t rather than t?, at the discretion of the class implementing t (e.g., null to Boolean === false). A class may define its own to operator using the following syntax:

class C extends B {
...
function to C(v) {...}
}

We will redefine the type conversions specified variously in Edition 3 Chapters 9 and 15 in terms of the to operator applied to the native classes.Our current thinking is that to conversions follow Chapter 9, except for any of (Null ∪ Void) to (String ∪ Object), which all result in null, not "null", "undefined", or a TypeError throw.

Type annotations

Testing and enforcing invariants using these type operators in expressions governing control flow is sometimes useful, but often tedious, error-prone, and bloaty. We wish for typed declarations that enable the language implementation to do the testing and enforcing for us. Therefore for each of the three type operators is, as,and to, there is a corresponding type annotation that may be used with var, const, and function declarations to specify type:

var v is t = x ≡ if (!(x is t)) throw TypeError; var v = x
var v as t = x ≡ var v = x as t
var v to t = x ≡ var v = x to t

The initializer is optional as usual; if missing, a sane default value for the annotated type is used. For all assignments v = x following such a type-annotated variable declaration, the production on the right of ≡ above, stripped of var, is evaluated. Function formal parameters and the function’s return value may be annotated similarly:

function f(a is int, b as Object, c to String) is Number {...}

Type annotations are optional. To support strict options that require every declaration to be annotated, * may be used for ⊤ (the top type), e.g. var v is *, which is equivalent to var v. Note that * is used differently for E4X, but its meaning as ⊤ is unambiguous in type operator and annotation right operand contexts.

In a nutshell, is t annotations insist on type t and defend against null and undefined (no more “foo has no properties” errors; with static analysis, an error that can’t be avoided at runtime can even be reported at compile time). as t annotations enforce (is t)-or-null invariance. And to t annotations convert according to cleaner, class-extensible rules.

Coming soon

In the next update, I’ll list the small number of incompatible changes to Edition 3 that we are considering. In a subsequent item, I will discuss stronger naming mechanisms to support programming in the large.

New Roadmaps

Mozilla is a huge project, now cursed with success. It did not start that way. To think about where to go, we should mull over how we got here.

Over the years since the first major roadmap, I’ve tried to steer the project toward the shortest path to the next port of call that was not going to leave us cannibalizing the ship and ourselves, for want of supplies and fresh crew (more contributors). Doing this without running out of stores and existing crew along the way required good luck, along with a hard-nosed attitude about what to keep and what to throw overboard.

Some paths were long, for instance the reset in late 1998 around Gecko, XPCOM, and an XPFE. This was a mistake in commercial software terms, but it was inevitable given Netscape management politics of the time, and more to the point, it was necessary for Mozilla’s long-term success. By resetting around Gecko, we opened up vast new territory in the codebase and the project for newcomers to homestead.

More recent journeys to better ports were much more in tune with the Internet zeitgeist. The best example was FIrefox as the new model application.

Firefox changed everything for us, for the industry, and most important, for browser users. We have heard repeatedly from people who feel as though their computers are friendly tools again, instead of spyware-ridden zombies infected via the default browser. These folks now see the web as fun and empowering, not static or even degrading over time.

Now, having given the default browser a little competition, and helped advance the causes of simple yet powerful UI, web content standards, and user innovation toolkits and networks such as XUL extensions, their own extensions (e.g., GreaseMonkey’s user scripts), and AJAX/DHTML/whatever new-style web apps, we must journey again to an even better place, with another hundred million downloads, and even more users worldwide.

We see the Web outpacing traditional desktop and operating system software development. Great web services and mashups abound in the new, over-hyped era. In spite of the hype, these new Web apps usefully point to the immense, hardly-realized value of people connected by the Internet.

Firefox is “just a browser”, but it has an evolving role to play in this world. The browser is a platform, as threatened in 1995 and dismissed with the death of Netscape. Yet every web app is hobbled by stagnant content standards from five or ten years ago. There is no good reason for this.

There is no reason why browsers should not innovate, along with plugins, applications, and operating systems, to support modern hardware-assisted graphics, dynamic programming languages, and richer content types. The reach of the web still favors the browser over any particular OS or non-Web platform.

Therefore in order to innovate nearer to “Web time” on the Firefox user interface and extension fronts, we propose to develop the front end of Firefox 2 and the platform for Firefox 3 concurrently, with Firefox 2 releasing in less than a year. The details have been drafted in a product roadmap that Chris Beard has written. (Many of you know Chris as an active driver and product manager in the project since Firefox 1.0 launched. He’s been a huge help, and I’m very grateful for his contribution here.)

The back end code, Gecko and other modules such as the JavaScript engine, will occupy the Mozilla source tree “trunk” development during the Gecko 1.9 milestone, which is already under way. The major efforts are to:

  • rearchitect our rendering layer to support hardware-accelerated graphics;
  • selectively improve architecture in the layout engine, to fix longstanding bugs;
  • improve web author productivity with better content languages and debugability;
  • move XUL to the next level in concert with the rendering and programming improvements;
  • make XULRunner the embedding vehicle for Firefox and all modern XUL applications.

Mike Shaver and I have gathered together the requirements and plans of many folks in a new platform roadmap.

These roadmap drafts are rough, and although much work has already been done in the directions outlined by these documents, much more remains, and our plans will change as needed. But plan we must, perhaps more than ever in the project’s history. We have reached the big time now, and there is no turning back or coasting along.

Your comments are welcome.

Recap and Prelude

Recap

Too much travel and conference fun, too little blogging:

I was invited to present a keynote at ACM ICFP 2005 in Tallinn, Estonia at the end of September. The very kind program comittee was unanimously interested in me as the ‘where the rubber meets the road’ speaker. I hope I delivered; I still have tire marks on my back from the Netscape 2 days.

It was an honor to speak and attend, and I made some good connections and introductions. Among these was Autrijus Tang, who is a hero in my book for promoting both Perl 6 and Haskell in one fell swoop. Functional programming is on the rise, and I’m glad that JS is playing a small (but very widely distributed) part.

While there, the Skype guys were nice enough to have me out to dinner — I hope to reciprocate when they’re in the bay area.

The old town in Tallinn is delightful, full of charming architecture from various eras going back to the high Middle Ages. I’m planning my move already (half-kidding).

After that came Web 2.0, which was a blur of VCs, old friends, and new companies. Everyone noticed the bubbly atmosphere. Mitchell was in fine form in a kind of interleaved interview titled Can Open Source Stay Open?

Prelude

I have been working more and more with ECMA TG1 on JavaScript standards, at first E4X (which was all but done when Mozilla joined ECMA last year) and now Edition 4. Our goals include:

  • Bringing Edition 4 back toward the current language, so that prototype based delegation is not a vestigial compatibility mode, but the dynamic part of an object system that includes classes with fixed members that cannot be overridden or shadowed.
  • Allowing implementors to bootstrap the language, expressing all the meta-object protocol magic used by the “native” objects (ECMA-262 Edition 3 section 15), including get/set/call/construct and control over property attributes such as enumerability.
  • Adding type annotations without breaking interoperation of existing and new editions, in support of programming in the large — which is needed more and more in XUL and modern web applications.
  • Fixing longstanding problems that bite almost every JS hacker, as I’ve discussed previously.

Our intention is to finish by the end of next year, and to implement and test interoperation along the way as much as possible. The Macromedia folks are quite far along in their implementation of a derivative of Waldemar’s Edition 4 draft, called ActionScript 3.

At the same time, and while also slaving over a hot Gecko 1.8 / Firefox 1.5 stove, I have been working with Mozilla leaders, especially shaver and other drivers, on roadmap-level plans for the next year to 15 months.

These plans build on bottom-up planning from module-sized projects such as the move to Cairo graphics as Gecko’s new graphics substrate, the Python for XUL project, and the XULRunner project. We aim to balance the need to ship Firefox releases that innovate quickly in user-facing ways with the longer cycle time required to uplift the web platform with better graphics features and content languages in Gecko 1.9.

The fruits of all this planning, in the form of a coherent draft overview containing links to project and wiki pages, and a schedule and branching plan for everyone to review, will be pushed out to https://www.mozilla.org/ imminently. The old roadmap page will contain at least links, if it doesn’t beome a redirect. Stay tuned.

Python for XUL scripting

I announced XUL support for Python at ETech to cheers, and now Mark Hammond has begun delivering the goods. See the DOM_AGNOSTIC_BRANCH for his work to enable Python (and other languages, but Python for sure, and other languages need their own champions to do some work) to be used when writing trusted XUL applications and extensions.

One of Mark’s first testcases, slightly abridged:

<window
xmlns="https://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="main-window" orient="vertical">
<script language="python">
<![CDATA[
import xpcom
for attr in "document parent top scrollbars name textZoom scrollX scrollY".split():
try:
val = getattr(this, attr)
except (xpcom.Exception, AttributeError), exc:
print "FAILED to get attribute %s: %s" % (attr, exc)
else:
print attr, "is", val
print "Scrollbar visible =", this.scrollbars.visible
promptService = xpcom.components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(xpcom.components.interfaces.nsIPromptService)
promptService.alert(this.window, "title", "Hello from Python");
]]>
</script>
</window>

A more recent example showing how to mix scripting languages:

// Some XUL that uses the default scripting language, JS:
<hbox id="language_box">
<button id="but_js" label="click for js"
oncommand="dump('hello from jsn');"/>
</hbox>
// A XUL overlay that uses Python by default:
<overlay ... scripttype="application/x-python">
<hbox id="language_box">
<button id="but_python" label="click for Python"
oncommand="print 'hello from Python'"/>
</hbox>
</overlay>

Python for XUL will be available in the Mozilla 1.9 milestone time frame, when the DOM_AGNOSTIC_BRANCH is landed some time this calendar year for sure, but then only in alpha releases and trunk nightly builds. The next major Firefox release based on the 1.9 milestone (Firefox 1.5 is based on the Mozilla 1.8 milestone) will include Mark’s work — but not a C-Python environment by default.

How Windows end users, and others who may not have Python installed already, will get it along with XUL that requires it, remains a problem to be solved. We have net stub installer technology, and now with Firefox 1.5, a patch-based incremental update system. I predict this problem will be solved quickly as great Python-based XUL extensions to Firefox, and new XUL applications built on Firefox or XULRunner, emerge and gain users.

Here is a good place to say that while I’ve been helping Firefox 1.5 quite a bit lately, and not working enough on JavaScript futures (about which I hoped to blog last month), I am finally clearing much of my schedule to work with colleagues in ECMA TG1, and with Mozilla hackers, to specify and implement a new version of the language. Since JS is not going away, and our demands on it grow daily, it should evolve.

Given evolving JS, why Python? Simple: different programming languages, of different ages, have their strengths, and one of the greatest strength of any solid language is its community. We want to support Python as well as JS for XUL scripting in order to engage a large, creative community of hackers that is mostly disjoint from the web-standards-savvy XUL hackers who are already engaged with Mozilla and Firefox.

We aim to broaden the appeal of our platform in several ways, and supporting Python for XUL is one achievable way to do that, thanks to Mark’s work back in the days when he was employed by Active State, and now that we have him engaged again for the Mozilla Foundation.

/be