diff --git a/build/build.sh b/build/build.sh
index bc29c1a4..f0769341 100755
--- a/build/build.sh
+++ b/build/build.sh
@@ -31,4 +31,4 @@ then
 fi
 
 ./preprocess.sh $MODE ../src/paper.js "-d '{ \"browser\": true }' -i '../src/constants.js'" ../dist/paper.js
-#./preprocess.sh $MODE ../src/paper.js "-d '{ \"server\": true }' -i '../src/constants.js'" ../dist/paper-server.js 
+#./preprocess.sh $MODE ../src/paper.js "-d '{ \"node\": true }' -i '../src/constants.js'" ../dist/paper-node.js 
diff --git a/build/preprocess.sh b/build/preprocess.sh
index 3482a6a2..6acfb1e9 100755
--- a/build/preprocess.sh
+++ b/build/preprocess.sh
@@ -24,10 +24,19 @@
 #	commented		Preprocessed, still formated and commented
 #	stripped		Preprocessed, formated but without comments
 
-VERSION=0.8
+# Get the date from the git log:
 DATE=$(git log -1 --pretty=format:%ad)
-
-COMMAND="./prepro.js -d '{ \"version\": $VERSION, \"date\": \"$DATE\", \"parser\": \"acorn\", \"svg\": true, \"fatline\": false }' $3 $2"
+# Extract the paper.js version from package.json:
+VERSION=$(node -e "
+	process.stdout.write(require('../package.json').version)
+")
+# Load and evaluate the options from options.js, and convert it an escaped json:
+OPTIONS=$(printf '%q' $(node -e "
+	eval(require('fs').readFileSync('../src/options.js', 'utf8'));
+	process.stdout.write(JSON.stringify(options));
+"))
+# Build the prepo.js command out of it, passing on version and date as defines:
+COMMAND="./prepro.js -d $OPTIONS -d '{ \"version\": \"$VERSION\", \"date\": \"$DATE\", \"stats\": false }' $3 $2"
 
 case $1 in
 	commented)
diff --git a/fatline/intersectTests.js b/fatline/intersectTests.js
index 2dfc2632..e9730862 100644
--- a/fatline/intersectTests.js
+++ b/fatline/intersectTests.js
@@ -1,4 +1,5 @@
-	
+// Uncomment this to turn on fatline clipping in paper.js too
+options.fatline = true;
 paper.install(window);
 
 /**
@@ -235,40 +236,40 @@ function runTests() {
 		prepareTest('Results - Boolean tests (Time taken per test)', container, 'big');
 		var x = 80.5, y = 15.5, width = 500, height = 190, i, txt, ny,
 			yy = y + height, xx = x + width;
-		var ppaperfill = new Path(), pfatfill = new Path();
-		var ppaper = new Path(), pfat = new Path();
-		var max = testdata.reduce(function(a, b) { return Math.max(a, b.paperTime + b.fatTime); }, 0) + 20;
+		var ppaper = new Path(),
+			pfat = new Path();
+		var max = testdata.reduce(function(a, b) {
+			return Math.max(a, b.paperTime + b.fatTime);
+		}, 0) + 20;
 		var vscale = height / max, hscale = width / testdata.length;
 		var caxes = '#999', ctxt = '#222', ctxt2 = '#555', cpaper = '#268BD2', cpaperfill ='#B5E1FF',
 			cfat = '#D33682', cfatfill = '#FFADD4';
-		new Path.Line(x, yy, xx, yy).style.strokeColor = caxes;
-		new Path.Line(x, yy, x, y).style.strokeColor = caxes;
+		new Path.Line(x, yy, xx, yy).strokeColor = caxes;
+		new Path.Line(x, yy, x, y).strokeColor = caxes;
 		for (i = 0; i < 10 ; i++) {
 			ny = yy - vscale * max * i / 10;
-			new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes;
+			new Path.Line(x, ny, x-5, ny).strokeColor = caxes;
 			txt = new PointText([x-10, ny]);
 			txt.justification = 'right';
 			txt.fillColor = (i%2)? ctxt: ctxt2;
 			txt.content = (max * i / 10).toFixed(1) + ((!i)? ' ms' : '');
 		}
-		ppaperfill.add(new Segment(x, yy));
-		pfatfill.add(new Segment(x, yy));
+		ppaper.add(x, yy);
+		pfat.add(x, yy);
 		var vx = x, clr = ctxt;
 		var coords = [], avgPaper = 0, avgFat = 0,
 			maxSpeedup = -Infinity, minSpeedup = Infinity, avgSpeedup = 0;
 		testdata.map(function(data) {
 			avgPaper += data.paperTime;
-			ny = yy - (data.paperTime + data.fatTime) * vscale;
-			ppaper.add(new Segment([vx, ny]));
-			ppaperfill.add(new Segment([vx, ny]));
+			ny = yy - (data.paperTime /*+ data.fatTime */) * vscale;
+			ppaper.add(vx, ny);
 			var np = new Point(vx, ny);
 			np._data = data;
 			np._datatype = 'paper';
 			coords.push(np);
 			avgFat += data.fatTime;
 			ny = yy - (data.fatTime) * vscale;
-			pfat.add(new Segment([vx, ny]));
-			pfatfill.add(new Segment([vx, ny]));
+			pfat.add(vx, ny);
 			np = new Point(vx, ny);
 			np._data = data;
 			np._datatype = 'fat';
@@ -279,7 +280,7 @@ function runTests() {
 			if (speedup < minSpeedup) minSpeedup = speedup;
 			avgSpeedup += speedup;
 
-			new Path.Line(vx, yy, vx, yy + 5).style.strokeColor = caxes;
+			new Path.Line(vx, yy, vx, yy + 5).strokeColor = caxes;
 			txt = new PointText([vx, yy+18]);
 			txt.justification = 'left';
 			txt.fillColor = clr;
@@ -288,23 +289,25 @@ function runTests() {
 
 			if (!data.success) {
 				var p = new Path.Line(vx, y, vx, yy);
-				p.style.strokeWidth = 5;
-				p.style.strokeColor = '#f00';
+				p.strokeWidth = 5;
+				p.strokeColor = '#f00';
 			}
 
 			clr = (clr === ctxt)? ctxt2 : ctxt;
 			vx += hscale;
 		});
-		ppaper.style.strokeWidth = 2;
-		ppaper.style.strokeColor = cpaper;
-		ppaperfill.add(new Segment(vx-hscale, yy));
-		ppaperfill.closed = true;
-		ppaperfill.style.fillColor = cpaperfill;
-		pfat.style.strokeWidth = 2;
-		pfat.style.strokeColor = cfat;
-		pfatfill.add(new Segment(vx-hscale, yy));
-		pfatfill.closed = true;
-		pfatfill.style.fillColor = cfatfill;
+		ppaper.strokeWidth = 2;
+		ppaper.strokeColor = cpaper;
+		ppaper.add(vx-hscale, yy);
+		ppaper.closed = true;
+		ppaper.fillColor = cpaperfill;
+		ppaper.opacity = 0.75;
+		pfat.strokeWidth = 2;
+		pfat.strokeColor = cfat;
+		pfat.add(vx-hscale, yy);
+		pfat.closed = true;
+		pfat.fillColor = cfatfill;
+		pfat.opacity = 0.75;
 
 		avgPaper/= testdata.length;
 		avgFat/= testdata.length;
@@ -312,13 +315,13 @@ function runTests() {
 		maxSpeedup = Math.round(maxSpeedup);
 		minSpeedup = Math.round(minSpeedup);
 		ny = Math.round(yy - avgPaper * vscale) + 0.5;
-		new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper;
+		new Path.Line(x, ny, xx, ny).strokeColor = cpaper;
 		txt = new PointText([xx, ny]);
 		txt.justification = 'right';
 		txt.fillColor = cpaper;
 		txt.content = avgPaper.toFixed(1);
 		ny = Math.round(yy - avgFat * vscale) + 0.5;
-		new Path.Line(x, ny, xx, ny).style.strokeColor = cfat;
+		new Path.Line(x, ny, xx, ny).strokeColor = cfat;
 		txt = new PointText([xx, ny]);
 		txt.justification = 'right';
 		txt.fillColor = cfat;
@@ -358,10 +361,10 @@ function runTests() {
 			if (dist > 500) { return; }
 			if (pnt && data) {
 				var p = new Path.Line(pnt.x+0.5, y, pnt.x+0.5, yy);
-				p.style.strokeColor = '#000';
+				p.strokeColor = '#000';
 				p.removeOnMove();
 				p = new Path.Circle(pnt, 3);
-				p.style.fillColor = (type === 'fat')? '#D33682' :'#268BD2';
+				p.fillColor = (type === 'fat')? '#D33682' :'#268BD2';
 				p.removeOnMove();
 				var txt = new PointText([ 500, 20 ]);
 				txt.content = 'subdiv : ' + data.paperTime.toFixed(1) + ' ms';
@@ -563,8 +566,8 @@ function markPoint(pnt, t, c, tc, remove) {
 	c = c || '#000';
 	if (remove === undefined) { remove = true; }
 	var cir = new Path.Circle(pnt, 2);
-	cir.style.fillColor = c;
-	cir.style.strokeColor = tc;
+	cir.fillColor = c;
+	cir.strokeColor = tc;
 	if (t !== undefined || t !== null) {
 		var text = new PointText(pnt.add([0, -3]));
 		text.justification = 'center';
@@ -588,7 +591,7 @@ function markCurve(crv, c, flag) {
 			new Segment([crv[0], crv[1]], null, [crv[2] - crv[0], crv[3] - crv[1]]),
 			new Segment([crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null)
 			);
-		window.__p1.style.strokeColor = c;
+		window.__p1.strokeColor = c;
 		// window.__p1.fullySelected = true;
 	} else {
 		if (window.__p2) window.__p2.remove();
@@ -596,7 +599,7 @@ function markCurve(crv, c, flag) {
 			new Segment([crv[0], crv[1]], null, [crv[2] - crv[0], crv[3] - crv[1]]),
 			new Segment([crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null)
 			);
-		window.__p2.style.strokeColor = c;
+		window.__p2.strokeColor = c;
 		// window.__p2.fullySelected = true;
 	}
 	view.draw();
@@ -624,8 +627,8 @@ function annotateSegment(s, t, c, tc, remove, skipCurves) {
 	var t1 = crv.getNormal(0).normalize(10);
 	var p = s.point.clone().add(t1);
 	var cir = new Path.Circle(s.point, 2);
-	cir.style.fillColor = c;
-	cir.style.strokeColor = tc;
+	cir.fillColor = c;
+	cir.strokeColor = tc;
 	var text = new PointText(p);
 	text.justification = 'center';
 	text.fillColor = c;
@@ -657,8 +660,8 @@ function annotateCurve(crv, t, c, tc, remove) {
 	text.justification = 'center';
 	text.fillColor = tc;
 	text.content = t;
-	l.style.strokeColor = l2.style.strokeColor = c;
-	cir.style.fillColor = c;
+	l.strokeColor = l2.strokeColor = c;
+	cir.fillColor = c;
 	if (remove) {
 		l.removeOnMove();
 		l2.removeOnMove();
@@ -677,11 +680,11 @@ function plotDataRandom(testdata) {
 	testdata.sort(function(a,b) { return a.ratio - b.ratio; });
 	var vscale = height / max, hscale = width / testdata.length;
 	var caxes = '#999', ctxt = '#222', cpaper = '#268BD2', cfat = '#D33682';
-	new Path.Line(x, yy, xx, yy).style.strokeColor = caxes;
-	new Path.Line(x, yy, x, y).style.strokeColor = caxes;
+	new Path.Line(x, yy, xx, yy).strokeColor = caxes;
+	new Path.Line(x, yy, x, y).strokeColor = caxes;
 	for (i = 0; i < 10 ; i++) {
 		ny = yy - vscale * max * i / 10;
-		new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes;
+		new Path.Line(x, ny, x-5, ny).strokeColor = caxes;
 		txt = new PointText([x-10, ny]);
 		txt.justification = 'right';
 		txt.fillColor = ctxt;
@@ -699,13 +702,13 @@ function plotDataRandom(testdata) {
 	var avgPaper = 0, avgFat = 0;
 	testdata.map(function(data) {
 		avgPaper += data.paperTime;
-		ny = yy - (data.paperTime + data.fatTime) * vscale;
-		ppaper.add(new Segment([vx, ny]));
+		ny = yy - (data.paperTime /* + data.fatTime*/) * vscale;
+		ppaper.add(vx, ny);
 		avgFat += data.fatTime;
 		ny = yy - (data.fatTime) * vscale;
-		pfat.add(new Segment([vx, ny]));
+		pfat.add(vx, ny);
 
-		new Path.Line(vx, yy, vx, yy + 5 + ((count%2)? step:0)).style.strokeColor = caxes;
+		new Path.Line(vx, yy, vx, yy + 5 + ((count%2)? step:0)).strokeColor = caxes;
 		txt = new PointText([vx, yy+18 + ((count%2)? step:0) ]);
 		txt.justification = 'center';
 		txt.fillColor = ctxt;
@@ -718,29 +721,31 @@ function plotDataRandom(testdata) {
 
 		if (!data.success) {
 			var p = new Path.Line(vx, y, vx, yy);
-			p.style.strokeWidth = 5;
-			p.style.strokeColor = '#f00';
+			p.strokeWidth = 5;
+			p.strokeColor = '#f00';
 		}
 		++count;
 		vx += hscale;
 	});
-	ppaper.smooth();
-	ppaper.style.strokeWidth = 2;
-	ppaper.style.strokeColor = cpaper;
-	pfat.smooth();
-	pfat.style.strokeWidth = 2;
-	pfat.style.strokeColor = cfat;
+//	ppaper.smooth();
+	ppaper.strokeWidth = 2;
+	ppaper.strokeColor = cpaper;
+	ppaper.opacity = 0.75;
+//	pfat.smooth();
+	pfat.strokeWidth = 2;
+	pfat.strokeColor = cfat;
+	pfat.opacity = 0.75;
 
 	avgPaper/= testdata.length;
 	avgFat/= testdata.length;
 	ny = Math.round(yy - avgPaper * vscale) + 0.5;
-	new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper;
+	new Path.Line(x, ny, xx, ny).strokeColor = cpaper;
 	txt = new PointText([xx, ny]);
 	txt.justification = 'right';
 	txt.fillColor = cpaper;
 	txt.content = avgPaper.toFixed(1);
 	ny = Math.round(yy - avgFat * vscale) + 0.5;
-	new Path.Line(x, ny, xx, ny).style.strokeColor = cfat;
+	new Path.Line(x, ny, xx, ny).strokeColor = cfat;
 	txt = new PointText([xx, ny]);
 	txt.justification = 'right';
 	txt.fillColor = cfat;
@@ -749,80 +754,78 @@ function plotDataRandom(testdata) {
 	view.draw();
 }
 
-
-
 function drawFatline(v1) {
-		function signum(num) {
-				return (num > 0)? 1 : (num < 0)? -1 : 0;
-		}
-		var l = new Line([v1[0], v1[1]], [v1[6], v1[7]], false);
-		var p1 = new Point(v1[2], v1[3]), p2 = new Point(v1[4], v1[5]);
-		var d1 = l.getSide(p1) * l.getDistance(p1) || 0;
-		var d2 = l.getSide(p2) * l.getDistance(p2) || 0;
-		var dmin, dmax;
-		if (d1 * d2 > 0) {
-				// 3/4 * min{0, d1, d2}
-				dmin = 0.75 * Math.min(0, d1, d2);
-				dmax = 0.75 * Math.max(0, d1, d2);
-		} else {
-				// 4/9 * min{0, d1, d2}
-				dmin = 4 * Math.min(0, d1, d2) / 9.0;
-				dmax = 4 * Math.max(0, d1, d2) / 9.0;
-		}
-		var ll = new Path.Line(v1[0], v1[1], v1[6], v1[7]);
-		window.__p3.push(ll);
-		window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9, 0.8);
-		var lp1 = ll.segments[0].point;
-		var lp2 = ll.segments[1].point;
-		var pm = l.vector, pm1 = pm.rotate(signum(dmin) * -90), pm2 = pm.rotate(signum(dmax) * -90);
-		var p11 = lp1.add(pm1.normalize(Math.abs(dmin)));
-		var p12 = lp2.add(pm1.normalize(Math.abs(dmin)));
-		var p21 = lp1.add(pm2.normalize(Math.abs(dmax)));
-		var p22 = lp2.add(pm2.normalize(Math.abs(dmax)));
-		window.__p3.push(new Path.Line(p11, p12));
-		window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9);
-		window.__p3.push(new Path.Line(p21, p22));
-		window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9);
+	function signum(num) {
+			return (num > 0)? 1 : (num < 0)? -1 : 0;
+	}
+	var l = new Line([v1[0], v1[1]], [v1[6], v1[7]], false);
+	var p1 = new Point(v1[2], v1[3]), p2 = new Point(v1[4], v1[5]);
+	var d1 = l.getSide(p1) * l.getDistance(p1) || 0;
+	var d2 = l.getSide(p2) * l.getDistance(p2) || 0;
+	var dmin, dmax;
+	if (d1 * d2 > 0) {
+			// 3/4 * min{0, d1, d2}
+			dmin = 0.75 * Math.min(0, d1, d2);
+			dmax = 0.75 * Math.max(0, d1, d2);
+	} else {
+			// 4/9 * min{0, d1, d2}
+			dmin = 4 * Math.min(0, d1, d2) / 9.0;
+			dmax = 4 * Math.max(0, d1, d2) / 9.0;
+	}
+	var ll = new Path.Line(v1[0], v1[1], v1[6], v1[7]);
+	window.__p3.push(ll);
+	window.__p3[window.__p3.length-1].strokeColor = new Color(0,0,0.9, 0.8);
+	var lp1 = ll.segments[0].point;
+	var lp2 = ll.segments[1].point;
+	var pm = l.vector, pm1 = pm.rotate(signum(dmin) * -90), pm2 = pm.rotate(signum(dmax) * -90);
+	var p11 = lp1.add(pm1.normalize(Math.abs(dmin)));
+	var p12 = lp2.add(pm1.normalize(Math.abs(dmin)));
+	var p21 = lp1.add(pm2.normalize(Math.abs(dmax)));
+	var p22 = lp2.add(pm2.normalize(Math.abs(dmax)));
+	window.__p3.push(new Path.Line(p11, p12));
+	window.__p3[window.__p3.length-1].strokeColor = new Color(0,0,0.9);
+	window.__p3.push(new Path.Line(p21, p22));
+	window.__p3[window.__p3.length-1].strokeColor = new Color(0,0,0.9);
 }
 
 function plotD_vs_t(x, y, arr, arr2, v, dmin, dmax, tmin, tmax, yscale, tvalue) {
-		yscale = yscale || 1;
-		new Path.Line(x, y-100, x, y+100).style.strokeColor = '#aaa';
-		new Path.Line(x, y, x + 200, y).style.strokeColor = '#aaa';
+	yscale = yscale || 1;
+	new Path.Line(x, y-100, x, y+100).strokeColor = '#aaa';
+	new Path.Line(x, y, x + 200, y).strokeColor = '#aaa';
 
-		var clr = (tvalue)? '#a00' : '#00a';
-		if (window.__p3) window.__p3.map(function(a) {a.remove();});
+	var clr = (tvalue)? '#a00' : '#00a';
+	if (window.__p3) window.__p3.map(function(a) {a.remove();});
 
-		window.__p3 = [];
+	window.__p3 = [];
 
-		drawFatline(v);
+	drawFatline(v);
 
-		window.__p3.push(new Path.Line(x, y + dmin * yscale, x + 200, y + dmin * yscale));
-		window.__p3[window.__p3.length-1].style.strokeColor = '#000';
-		window.__p3.push(new Path.Line(x, y + dmax * yscale, x + 200, y + dmax * yscale));
-		window.__p3[window.__p3.length-1].style.strokeColor = '#000';
-		window.__p3.push(new Path.Line(x + tmin * 190, y-100, x + tmin * 190, y+100));
-		window.__p3[window.__p3.length-1].style.strokeColor = clr;
-		window.__p3.push(new Path.Line(x + tmax * 190, y-100, x + tmax * 190, y+100));
-		window.__p3[window.__p3.length-1].style.strokeColor = clr;
+	window.__p3.push(new Path.Line(x, y + dmin * yscale, x + 200, y + dmin * yscale));
+	window.__p3[window.__p3.length-1].strokeColor = '#000';
+	window.__p3.push(new Path.Line(x, y + dmax * yscale, x + 200, y + dmax * yscale));
+	window.__p3[window.__p3.length-1].strokeColor = '#000';
+	window.__p3.push(new Path.Line(x + tmin * 190, y-100, x + tmin * 190, y+100));
+	window.__p3[window.__p3.length-1].strokeColor = clr;
+	window.__p3.push(new Path.Line(x + tmax * 190, y-100, x + tmax * 190, y+100));
+	window.__p3[window.__p3.length-1].strokeColor = clr;
 
-		for (var i = 0; i < arr.length; i++) {
-				window.__p3.push(new Path.Line(new Point(x + arr[i][0] * 190, y + arr[i][1] * yscale),
-					new Point(x + arr[i][2] * 190, y + arr[i][3] * yscale)));
-				window.__p3[window.__p3.length-1].style.strokeColor = '#999';
-		}
-		var pnt = [];
-		var arr2x = [ 0.0, 0.333333333, 0.6666666666, 1.0 ];
-		for (var i = 0; i < arr2.length; i++) {
-				pnt.push(new Point(x + arr2x[i] * 190, y + arr2[i] * yscale));
-				window.__p3.push(new Path.Circle(pnt[pnt.length-1], 2));
-				window.__p3[window.__p3.length-1].style.fillColor = '#000';
-		}
-		// var pth = new Path(pnt[0], pnt[1], pnt[2], pnt[3]);
-		// pth.closed = true;
-		window.__p3.push(new Path(
-			new Segment(pnt[0], null, pnt[1].subtract(pnt[0])),
-			new Segment(pnt[3], pnt[2].subtract(pnt[3]), null)));
-		window.__p3[window.__p3.length-1].style.strokeColor = clr;
-		view.draw();
+	for (var i = 0; i < arr.length; i++) {
+			window.__p3.push(new Path.Line(new Point(x + arr[i][0] * 190, y + arr[i][1] * yscale),
+				new Point(x + arr[i][2] * 190, y + arr[i][3] * yscale)));
+			window.__p3[window.__p3.length-1].strokeColor = '#999';
+	}
+	var pnt = [];
+	var arr2x = [ 0.0, 0.333333333, 0.6666666666, 1.0 ];
+	for (var i = 0; i < arr2.length; i++) {
+			pnt.push(new Point(x + arr2x[i] * 190, y + arr2[i] * yscale));
+			window.__p3.push(new Path.Circle(pnt[pnt.length-1], 2));
+			window.__p3[window.__p3.length-1].fillColor = '#000';
+	}
+	// var pth = new Path(pnt[0], pnt[1], pnt[2], pnt[3]);
+	// pth.closed = true;
+	window.__p3.push(new Path(
+		new Segment(pnt[0], null, pnt[1].subtract(pnt[0])),
+		new Segment(pnt[3], pnt[2].subtract(pnt[3]), null)));
+	window.__p3[window.__p3.length-1].strokeColor = clr;
+	view.draw();
 }
diff --git a/lib/acorn-min.js b/lib/acorn-min.js
index 80abac98..b9296864 100644
--- a/lib/acorn-min.js
+++ b/lib/acorn-min.js
@@ -1 +1 @@
-(function(e){return"object"==typeof exports&&"object"==typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):(e(this.acorn||(this.acorn={})),void 0)})(function(e){"use strict";function r(e){fr=e||{};for(var r in hr)fr.hasOwnProperty(r)||(fr[r]=hr[r]);mr=fr.sourceFile||null}function t(e,r){var t=vr(pr,e);r+=" ("+t.line+":"+t.column+")";var n=new SyntaxError(r);throw n.pos=e,n.loc=t,n.raisedAt=br,n}function n(e){function r(e){if(1==e.length)return t+="return str === "+JSON.stringify(e[0])+";";t+="switch(str){";for(var r=0;e.length>r;++r)t+="case "+JSON.stringify(e[r])+":";t+="return true}return false;"}e=e.split(" ");var t="",n=[];e:for(var a=0;e.length>a;++a){for(var o=0;n.length>o;++o)if(n[o][0].length==e[a].length){n[o].push(e[a]);continue e}n.push([e[a]])}if(n.length>3){n.sort(function(e,r){return r.length-e.length}),t+="switch(str.length){";for(var a=0;n.length>a;++a){var i=n[a];t+="case "+i[0].length+":",r(i)}t+="}"}else r(e);return Function("str",t)}function a(){this.line=Ar,this.column=br-Sr}function o(){Ar=1,br=Sr=0,Er=!0,u()}function i(e,r){gr=br,fr.locations&&(kr=new a),wr=e,u(),Cr=r,Er=e.beforeExpr}function s(){var e=fr.onComment&&fr.locations&&new a,r=br,n=pr.indexOf("*/",br+=2);if(-1===n&&t(br-2,"Unterminated comment"),br=n+2,fr.locations){Kt.lastIndex=r;for(var o;(o=Kt.exec(pr))&&br>o.index;)++Ar,Sr=o.index+o[0].length}fr.onComment&&fr.onComment(!0,pr.slice(r+2,n),r,br,e,fr.locations&&new a)}function c(){for(var e=br,r=fr.onComment&&fr.locations&&new a,t=pr.charCodeAt(br+=2);dr>br&&10!==t&&13!==t&&8232!==t&&8329!==t;)++br,t=pr.charCodeAt(br);fr.onComment&&fr.onComment(!1,pr.slice(e+2,br),e,br,r,fr.locations&&new a)}function u(){for(;dr>br;){var e=pr.charCodeAt(br);if(32===e)++br;else if(13===e){++br;var r=pr.charCodeAt(br);10===r&&++br,fr.locations&&(++Ar,Sr=br)}else if(10===e)++br,++Ar,Sr=br;else if(14>e&&e>8)++br;else if(47===e){var r=pr.charCodeAt(br+1);if(42===r)s();else{if(47!==r)break;c()}}else if(14>e&&e>8||32===e||160===e)++br;else{if(!(e>=5760&&Wt.test(String.fromCharCode(e))))break;++br}}}function l(){var e=pr.charCodeAt(br+1);return e>=48&&57>=e?E(!0):(++br,i(gt))}function f(){var e=pr.charCodeAt(br+1);return Er?(++br,k()):61===e?x(Ct,2):x(kt,1)}function p(){var e=pr.charCodeAt(br+1);return 61===e?x(Ct,2):x(Ot,1)}function d(e){var r=pr.charCodeAt(br+1);return r===e?x(124===e?It:Lt,2):61===r?x(Ct,2):x(124===e?Ut:Tt,1)}function m(){var e=pr.charCodeAt(br+1);return 61===e?x(Ct,2):x(Rt,1)}function h(e){var r=pr.charCodeAt(br+1);return r===e?x(At,2):61===r?x(Ct,2):x(Et,1)}function v(e){var r=pr.charCodeAt(br+1),t=1;return r===e?(t=62===e&&62===pr.charCodeAt(br+2)?3:2,61===pr.charCodeAt(br+t)?x(Ct,t+1):x(Ft,t)):(61===r&&(t=61===pr.charCodeAt(br+2)?3:2),x(qt,t))}function b(e){var r=pr.charCodeAt(br+1);return 61===r?x(Vt,61===pr.charCodeAt(br+2)?3:2):x(61===e?wt:St,1)}function y(e){switch(e){case 46:return l();case 40:return++br,i(mt);case 41:return++br,i(ht);case 59:return++br,i(bt);case 44:return++br,i(vt);case 91:return++br,i(lt);case 93:return++br,i(ft);case 123:return++br,i(pt);case 125:return++br,i(dt);case 58:return++br,i(yt);case 63:return++br,i(xt);case 48:var r=pr.charCodeAt(br+1);if(120===r||88===r)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return E(!1);case 34:case 39:return A(e);case 47:return f(e);case 37:case 42:return p();case 124:case 38:return d(e);case 94:return m();case 43:case 45:return h(e);case 60:case 62:return v(e);case 61:case 33:return b(e);case 126:return x(St,1)}return!1}function g(e){if(e?br=yr+1:yr=br,fr.locations&&(xr=new a),e)return k();if(br>=dr)return i(Dr);var r=pr.charCodeAt(br);if(Qt(r)||92===r)return L();var n=y(r);if(n===!1){var o=String.fromCharCode(r);if("\\"===o||$t.test(o))return L();t(br,"Unexpected character '"+o+"'")}return n}function x(e,r){var t=pr.slice(br,br+r);br+=r,i(e,t)}function k(){for(var e,r,n="",a=br;;){br>=dr&&t(a,"Unterminated regular expression");var o=pr.charAt(br);if(Ht.test(o)&&t(a,"Unterminated regular expression"),e)e=!1;else{if("["===o)r=!0;else if("]"===o&&r)r=!1;else if("/"===o&&!r)break;e="\\"===o}++br}var n=pr.slice(a,br);++br;var s=I();return s&&!/^[gmsiy]*$/.test(s)&&t(a,"Invalid regexp flag"),i(Fr,RegExp(n,s))}function w(e,r){for(var t=br,n=0,a=0,o=null==r?1/0:r;o>a;++a){var i,s=pr.charCodeAt(br);if(i=s>=97?s-97+10:s>=65?s-65+10:s>=48&&57>=s?s-48:1/0,i>=e)break;++br,n=n*e+i}return br===t||null!=r&&br-t!==r?null:n}function C(){br+=2;var e=w(16);return null==e&&t(yr+2,"Expected hexadecimal number"),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number"),i(qr,e)}function E(e){var r=br,n=!1,a=48===pr.charCodeAt(br);e||null!==w(10)||t(r,"Invalid number"),46===pr.charCodeAt(br)&&(++br,w(10),n=!0);var o=pr.charCodeAt(br);(69===o||101===o)&&(o=pr.charCodeAt(++br),(43===o||45===o)&&++br,null===w(10)&&t(r,"Invalid number"),n=!0),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number");var s,c=pr.slice(r,br);return n?s=parseFloat(c):a&&1!==c.length?/[89]/.test(c)||Vr?t(r,"Invalid number"):s=parseInt(c,8):s=parseInt(c,10),i(qr,s)}function A(e){br++;for(var r="";;){br>=dr&&t(yr,"Unterminated string constant");var n=pr.charCodeAt(br);if(n===e)return++br,i(Or,r);if(92===n){n=pr.charCodeAt(++br);var a=/^[0-7]+/.exec(pr.slice(br,br+3));for(a&&(a=a[0]);a&&parseInt(a,8)>255;)a=a.slice(0,a.length-1);if("0"===a&&(a=null),++br,a)Vr&&t(br-2,"Octal literal in strict mode"),r+=String.fromCharCode(parseInt(a,8)),br+=a.length-1;else switch(n){case 110:r+="\n";break;case 114:r+="\r";break;case 120:r+=String.fromCharCode(S(2));break;case 117:r+=String.fromCharCode(S(4));break;case 85:r+=String.fromCharCode(S(8));break;case 116:r+="	";break;case 98:r+="\b";break;case 118:r+="";break;case 102:r+="\f";break;case 48:r+="\0";break;case 13:10===pr.charCodeAt(br)&&++br;case 10:fr.locations&&(Sr=br,++Ar);break;default:r+=String.fromCharCode(n)}}else(13===n||10===n||8232===n||8329===n)&&t(yr,"Unterminated string constant"),r+=String.fromCharCode(n),++br}}function S(e){var r=w(16,e);return null===r&&t(yr,"Bad character escape sequence"),r}function I(){Dt=!1;for(var e,r=!0,n=br;;){var a=pr.charCodeAt(br);if(Yt(a))Dt&&(e+=pr.charAt(br)),++br;else{if(92!==a)break;Dt||(e=pr.slice(n,br)),Dt=!0,117!=pr.charCodeAt(++br)&&t(br,"Expecting Unicode escape sequence \\uXXXX"),++br;var o=S(4),i=String.fromCharCode(o);i||t(br-1,"Invalid Unicode escape"),(r?Qt(o):Yt(o))||t(br-4,"Invalid Unicode escape"),e+=i}r=!1}return Dt?e:pr.slice(n,br)}function L(){var e=I(),r=jr;return Dt||(Nt(e)?r=ut[e]:(fr.forbidReserved&&(3===fr.ecmaVersion?Bt:Mt)(e)||Vr&&zt(e))&&t(yr,"The keyword '"+e+"' is reserved")),i(r,e)}function U(){Ir=yr,Lr=gr,Ur=kr,g()}function R(e){for(Vr=e,br=Lr;Sr>br;)Sr=pr.lastIndexOf("\n",Sr-2)+1,--Ar;u(),g()}function T(){this.type=null,this.start=yr,this.end=null}function V(){this.start=xr,this.end=null,null!==mr&&(this.source=mr)}function q(){var e=new T;return fr.locations&&(e.loc=new V),fr.ranges&&(e.range=[yr,0]),e}function F(e){var r=new T;return r.start=e.start,fr.locations&&(r.loc=new V,r.loc.start=e.loc.start),fr.ranges&&(r.range=[e.range[0],0]),r}function O(e,r){return e.type=r,e.end=Lr,fr.locations&&(e.loc.end=Ur),fr.ranges&&(e.range[1]=Lr),e}function j(e){return fr.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.value}function D(e){return wr===e?(U(),!0):void 0}function B(){return!fr.strictSemicolons&&(wr===Dr||wr===dt||Ht.test(pr.slice(Lr,yr)))}function M(){D(bt)||B()||X()}function z(e){wr===e?U():X()}function X(){t(yr,"Unexpected token")}function N(e){"Identifier"!==e.type&&"MemberExpression"!==e.type&&t(e.start,"Assigning to rvalue"),Vr&&"Identifier"===e.type&&Xt(e.name)&&t(e.start,"Assigning to "+e.name+" in strict mode")}function W(e){Ir=Lr=br,fr.locations&&(Ur=new a),Rr=Vr=null,Tr=[],g();var r=e||q(),t=!0;for(e||(r.body=[]);wr!==Dr;){var n=J();r.body.push(n),t&&j(n)&&R(!0),t=!1}return O(r,"Program")}function J(){wr===kt&&g(!0);var e=wr,r=q();switch(e){case Br:case Xr:U();var n=e===Br;D(bt)||B()?r.label=null:wr!==jr?X():(r.label=lr(),M());for(var a=0;Tr.length>a;++a){var o=Tr[a];if(null==r.label||o.name===r.label.name){if(null!=o.kind&&(n||"loop"===o.kind))break;if(r.label&&n)break}}return a===Tr.length&&t(r.start,"Unsyntactic "+e.keyword),O(r,n?"BreakStatement":"ContinueStatement");case Nr:return U(),M(),O(r,"DebuggerStatement");case Jr:return U(),Tr.push(Zt),r.body=J(),Tr.pop(),z(rt),r.test=P(),M(),O(r,"DoWhileStatement");case Gr:if(U(),Tr.push(Zt),z(mt),wr===bt)return G(r,null);if(wr===et){var i=q();return U(),K(i,!0),1===i.declarations.length&&D(ct)?H(r,i):G(r,i)}var i=Q(!1,!0);return D(ct)?(N(i),H(r,i)):G(r,i);case Hr:return U(),cr(r,!0);case Kr:return U(),r.test=P(),r.consequent=J(),r.alternate=D(Pr)?J():null,O(r,"IfStatement");case Qr:return Rr||t(yr,"'return' outside of function"),U(),D(bt)||B()?r.argument=null:(r.argument=Q(),M()),O(r,"ReturnStatement");case Yr:U(),r.discriminant=P(),r.cases=[],z(pt),Tr.push(_t);for(var s,c;wr!=dt;)if(wr===Mr||wr===Wr){var u=wr===Mr;s&&O(s,"SwitchCase"),r.cases.push(s=q()),s.consequent=[],U(),u?s.test=Q():(c&&t(Ir,"Multiple default clauses"),c=!0,s.test=null),z(yt)}else s||X(),s.consequent.push(J());return s&&O(s,"SwitchCase"),U(),Tr.pop(),O(r,"SwitchStatement");case Zr:return U(),Ht.test(pr.slice(Lr,yr))&&t(Lr,"Illegal newline after throw"),r.argument=Q(),M(),O(r,"ThrowStatement");case _r:if(U(),r.block=$(),r.handler=null,wr===zr){var l=q();U(),z(mt),l.param=lr(),Vr&&Xt(l.param.name)&&t(l.param.start,"Binding "+l.param.name+" in strict mode"),z(ht),l.guard=null,l.body=$(),r.handler=O(l,"CatchClause")}return r.finalizer=D($r)?$():null,r.handler||r.finalizer||t(r.start,"Missing catch or finally clause"),O(r,"TryStatement");case et:return U(),r=K(r),M(),r;case rt:return U(),r.test=P(),Tr.push(Zt),r.body=J(),Tr.pop(),O(r,"WhileStatement");case tt:return Vr&&t(yr,"'with' in strict mode"),U(),r.object=P(),r.body=J(),O(r,"WithStatement");case pt:return $();case bt:return U(),O(r,"EmptyStatement");default:var f=Cr,p=Q();if(e===jr&&"Identifier"===p.type&&D(yt)){for(var a=0;Tr.length>a;++a)Tr[a].name===f&&t(p.start,"Label '"+f+"' is already declared");var d=wr.isLoop?"loop":wr===Yr?"switch":null;return Tr.push({name:f,kind:d}),r.body=J(),Tr.pop(),r.label=p,O(r,"LabeledStatement")}return r.expression=p,M(),O(r,"ExpressionStatement")}}function P(){z(mt);var e=Q();return z(ht),e}function $(){var e,r=q(),t=!0,n=!1;for(r.body=[],z(pt);!D(dt);){var a=J();r.body.push(a),t&&j(a)&&(e=n,R(n=!0)),t=!1}return n&&!e&&R(!1),O(r,"BlockStatement")}function G(e,r){return e.init=r,z(bt),e.test=wr===bt?null:Q(),z(bt),e.update=wr===ht?null:Q(),z(ht),e.body=J(),Tr.pop(),O(e,"ForStatement")}function H(e,r){return e.left=r,e.right=Q(),z(ht),e.body=J(),Tr.pop(),O(e,"ForInStatement")}function K(e,r){for(e.declarations=[],e.kind="var";;){var n=q();if(n.id=lr(),Vr&&Xt(n.id.name)&&t(n.id.start,"Binding "+n.id.name+" in strict mode"),n.init=D(wt)?Q(!0,r):null,e.declarations.push(O(n,"VariableDeclarator")),!D(vt))break}return O(e,"VariableDeclaration")}function Q(e,r){var t=Y(r);if(!e&&wr===vt){var n=F(t);for(n.expressions=[t];D(vt);)n.expressions.push(Y(r));return O(n,"SequenceExpression")}return t}function Y(e){var r=Z(e);if(wr.isAssign){var t=F(r);return t.operator=Cr,t.left=r,U(),t.right=Y(e),N(r),O(t,"AssignmentExpression")}return r}function Z(e){var r=_(e);if(D(xt)){var t=F(r);return t.test=r,t.consequent=Q(!0),z(yt),t.alternate=Q(!0,e),O(t,"ConditionalExpression")}return r}function _(e){return er(rr(e),-1,e)}function er(e,r,t){var n=wr.binop;if(null!=n&&(!t||wr!==ct)&&n>r){var a=F(e);a.left=e,a.operator=Cr,U(),a.right=er(rr(t),n,t);var a=O(a,/&&|\|\|/.test(a.operator)?"LogicalExpression":"BinaryExpression");return er(a,r,t)}return e}function rr(e){if(wr.prefix){var r=q(),n=wr.isUpdate;return r.operator=Cr,r.prefix=!0,U(),r.argument=rr(e),n?N(r.argument):Vr&&"delete"===r.operator&&"Identifier"===r.argument.type&&t(r.start,"Deleting local variable in strict mode"),O(r,n?"UpdateExpression":"UnaryExpression")}for(var a=tr();wr.postfix&&!B();){var r=F(a);r.operator=Cr,r.prefix=!1,r.argument=a,N(a),U(),a=O(r,"UpdateExpression")}return a}function tr(){return nr(ar())}function nr(e,r){if(D(gt)){var t=F(e);return t.object=e,t.property=lr(!0),t.computed=!1,nr(O(t,"MemberExpression"),r)}if(D(lt)){var t=F(e);return t.object=e,t.property=Q(),t.computed=!0,z(ft),nr(O(t,"MemberExpression"),r)}if(!r&&D(mt)){var t=F(e);return t.callee=e,t.arguments=ur(ht,!1),nr(O(t,"CallExpression"),r)}return e}function ar(){switch(wr){case at:var e=q();return U(),O(e,"ThisExpression");case jr:return lr();case qr:case Or:case Fr:var e=q();return e.value=Cr,e.raw=pr.slice(yr,gr),U(),O(e,"Literal");case ot:case it:case st:var e=q();return e.value=wr.atomValue,e.raw=wr.keyword,U(),O(e,"Literal");case mt:var r=xr,t=yr;U();var n=Q();return n.start=t,n.end=gr,fr.locations&&(n.loc.start=r,n.loc.end=kr),fr.ranges&&(n.range=[t,gr]),z(ht),n;case lt:var e=q();return U(),e.elements=ur(ft,!0,!0),O(e,"ArrayExpression");case pt:return ir();case Hr:var e=q();return U(),cr(e,!1);case nt:return or();default:X()}}function or(){var e=q();return U(),e.callee=nr(ar(),!0),e.arguments=D(mt)?ur(ht,!1):[],O(e,"NewExpression")}function ir(){var e=q(),r=!0,n=!1;for(e.properties=[],U();!D(dt);){if(r)r=!1;else if(z(vt),fr.allowTrailingCommas&&D(dt))break;var a,o={key:sr()},i=!1;if(D(yt)?(o.value=Q(!0),a=o.kind="init"):fr.ecmaVersion>=5&&"Identifier"===o.key.type&&("get"===o.key.name||"set"===o.key.name)?(i=n=!0,a=o.kind=o.key.name,o.key=sr(),wr!==mt&&X(),o.value=cr(q(),!1)):X(),"Identifier"===o.key.type&&(Vr||n))for(var s=0;e.properties.length>s;++s){var c=e.properties[s];if(c.key.name===o.key.name){var u=a==c.kind||i&&"init"===c.kind||"init"===a&&("get"===c.kind||"set"===c.kind);u&&!Vr&&"init"===a&&"init"===c.kind&&(u=!1),u&&t(o.key.start,"Redefinition of property")}}e.properties.push(o)}return O(e,"ObjectExpression")}function sr(){return wr===qr||wr===Or?ar():lr(!0)}function cr(e,r){wr===jr?e.id=lr():r?X():e.id=null,e.params=[];var n=!0;for(z(mt);!D(ht);)n?n=!1:z(vt),e.params.push(lr());var a=Rr,o=Tr;if(Rr=!0,Tr=[],e.body=$(!0),Rr=a,Tr=o,Vr||e.body.body.length&&j(e.body.body[0]))for(var i=e.id?-1:0;e.params.length>i;++i){var s=0>i?e.id:e.params[i];if((zt(s.name)||Xt(s.name))&&t(s.start,"Defining '"+s.name+"' in strict mode"),i>=0)for(var c=0;i>c;++c)s.name===e.params[c].name&&t(s.start,"Argument name clash in strict mode")}return O(e,r?"FunctionDeclaration":"FunctionExpression")}function ur(e,r,t){for(var n=[],a=!0;!D(e);){if(a)a=!1;else if(z(vt),r&&fr.allowTrailingCommas&&D(e))break;t&&wr===vt?n.push(null):n.push(Q(!0))}return n}function lr(e){var r=q();return r.name=wr===jr?Cr:e&&!fr.forbidReserved&&wr.keyword||X(),U(),O(r,"Identifier")}e.version="0.2.01";var fr,pr,dr,mr;e.parse=function(e,t){return pr=e+"",dr=pr.length,r(t),o(),W(fr.program)};var hr=e.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null},vr=e.getLineInfo=function(e,r){for(var t=1,n=0;;){Kt.lastIndex=n;var a=Kt.exec(e);if(!(a&&r>a.index))break;++t,n=a.index+a[0].length}return{line:t,column:r-n}};e.tokenize=function(e,t){function n(e){return g(e),a.start=yr,a.end=gr,a.startLoc=xr,a.endLoc=kr,a.type=wr,a.value=Cr,a}pr=e+"",dr=pr.length,r(t),o();var a={};return n.jumpTo=function(e,r){if(br=e,fr.locations){Ar=Sr=Kt.lastIndex=0;for(var t;(t=Kt.exec(pr))&&e>t.index;)++Ar,Sr=t.index+t[0].length}pr.charAt(e-1),Er=r,u()},n};var br,yr,gr,xr,kr,wr,Cr,Er,Ar,Sr,Ir,Lr,Ur,Rr,Tr,Vr,qr={type:"num"},Fr={type:"regexp"},Or={type:"string"},jr={type:"name"},Dr={type:"eof"},Br={keyword:"break"},Mr={keyword:"case",beforeExpr:!0},zr={keyword:"catch"},Xr={keyword:"continue"},Nr={keyword:"debugger"},Wr={keyword:"default"},Jr={keyword:"do",isLoop:!0},Pr={keyword:"else",beforeExpr:!0},$r={keyword:"finally"},Gr={keyword:"for",isLoop:!0},Hr={keyword:"function"},Kr={keyword:"if"},Qr={keyword:"return",beforeExpr:!0},Yr={keyword:"switch"},Zr={keyword:"throw",beforeExpr:!0},_r={keyword:"try"},et={keyword:"var"},rt={keyword:"while",isLoop:!0},tt={keyword:"with"},nt={keyword:"new",beforeExpr:!0},at={keyword:"this"},ot={keyword:"null",atomValue:null},it={keyword:"true",atomValue:!0},st={keyword:"false",atomValue:!1},ct={keyword:"in",binop:7,beforeExpr:!0},ut={"break":Br,"case":Mr,"catch":zr,"continue":Xr,"debugger":Nr,"default":Wr,"do":Jr,"else":Pr,"finally":$r,"for":Gr,"function":Hr,"if":Kr,"return":Qr,"switch":Yr,"throw":Zr,"try":_r,"var":et,"while":rt,"with":tt,"null":ot,"true":it,"false":st,"new":nt,"in":ct,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":at,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},lt={type:"[",beforeExpr:!0},ft={type:"]"},pt={type:"{",beforeExpr:!0},dt={type:"}"},mt={type:"(",beforeExpr:!0},ht={type:")"},vt={type:",",beforeExpr:!0},bt={type:";",beforeExpr:!0},yt={type:":",beforeExpr:!0},gt={type:"."},xt={type:"?",beforeExpr:!0},kt={binop:10,beforeExpr:!0},wt={isAssign:!0,beforeExpr:!0},Ct={isAssign:!0,beforeExpr:!0},Et={binop:9,prefix:!0,beforeExpr:!0},At={postfix:!0,prefix:!0,isUpdate:!0},St={prefix:!0,beforeExpr:!0},It={binop:1,beforeExpr:!0},Lt={binop:2,beforeExpr:!0},Ut={binop:3,beforeExpr:!0},Rt={binop:4,beforeExpr:!0},Tt={binop:5,beforeExpr:!0},Vt={binop:6,beforeExpr:!0},qt={binop:7,beforeExpr:!0},Ft={binop:8,beforeExpr:!0},Ot={binop:10,beforeExpr:!0};e.tokTypes={bracketL:lt,bracketR:ft,braceL:pt,braceR:dt,parenL:mt,parenR:ht,comma:vt,semi:bt,colon:yt,dot:gt,question:xt,slash:kt,eq:wt,name:jr,eof:Dr,num:qr,regexp:Fr,string:Or};for(var jt in ut)e.tokTypes[jt]=ut[jt];var Dt,Bt=n("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),Mt=n("class enum extends super const export import"),zt=n("implements interface let package private protected public static yield"),Xt=n("eval arguments"),Nt=n("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Wt=/[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/,Jt="\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",Pt="\u0371-\u0374\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",$t=RegExp("["+Jt+"]"),Gt=RegExp("["+Jt+Pt+"]"),Ht=/[\n\r\u2028\u2029]/,Kt=/\r\n|[\n\r\u2028\u2029]/g,Qt=e.isIdentifierStart=function(e){return 65>e?36===e:91>e?!0:97>e?95===e:123>e?!0:e>=170&&$t.test(String.fromCharCode(e))},Yt=e.isIdentifierChar=function(e){return 48>e?36===e:58>e?!0:65>e?!1:91>e?!0:97>e?95===e:123>e?!0:e>=170&&Gt.test(String.fromCharCode(e))},Zt={kind:"loop"},_t={kind:"switch"}});
\ No newline at end of file
+(function(e){return"object"==typeof exports&&"object"==typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):(e(this.acorn||(this.acorn={})),void 0)})(function(e){"use strict";function r(e){fr=e||{};for(var r in hr)fr.hasOwnProperty(r)||(fr[r]=hr[r]);mr=fr.sourceFile||null}function t(e,r){var t=vr(pr,e);r+=" ("+t.line+":"+t.column+")";var n=new SyntaxError(r);throw n.pos=e,n.loc=t,n.raisedAt=br,n}function n(e){function r(e){if(1==e.length)return t+="return str === "+JSON.stringify(e[0])+";";t+="switch(str){";for(var r=0;e.length>r;++r)t+="case "+JSON.stringify(e[r])+":";t+="return true}return false;"}e=e.split(" ");var t="",n=[];e:for(var a=0;e.length>a;++a){for(var o=0;n.length>o;++o)if(n[o][0].length==e[a].length){n[o].push(e[a]);continue e}n.push([e[a]])}if(n.length>3){n.sort(function(e,r){return r.length-e.length}),t+="switch(str.length){";for(var a=0;n.length>a;++a){var i=n[a];t+="case "+i[0].length+":",r(i)}t+="}"}else r(e);return Function("str",t)}function a(){this.line=Ar,this.column=br-Sr}function o(){Ar=1,br=Sr=0,Er=!0,u()}function i(e,r){gr=br,fr.locations&&(kr=new a),wr=e,u(),Cr=r,Er=e.beforeExpr}function s(){var e=fr.onComment&&fr.locations&&new a,r=br,n=pr.indexOf("*/",br+=2);if(-1===n&&t(br-2,"Unterminated comment"),br=n+2,fr.locations){Kt.lastIndex=r;for(var o;(o=Kt.exec(pr))&&br>o.index;)++Ar,Sr=o.index+o[0].length}fr.onComment&&fr.onComment(!0,pr.slice(r+2,n),r,br,e,fr.locations&&new a)}function c(){for(var e=br,r=fr.onComment&&fr.locations&&new a,t=pr.charCodeAt(br+=2);dr>br&&10!==t&&13!==t&&8232!==t&&8329!==t;)++br,t=pr.charCodeAt(br);fr.onComment&&fr.onComment(!1,pr.slice(e+2,br),e,br,r,fr.locations&&new a)}function u(){for(;dr>br;){var e=pr.charCodeAt(br);if(32===e)++br;else if(13===e){++br;var r=pr.charCodeAt(br);10===r&&++br,fr.locations&&(++Ar,Sr=br)}else if(10===e)++br,++Ar,Sr=br;else if(14>e&&e>8)++br;else if(47===e){var r=pr.charCodeAt(br+1);if(42===r)s();else{if(47!==r)break;c()}}else if(14>e&&e>8||32===e||160===e)++br;else{if(!(e>=5760&&Wt.test(String.fromCharCode(e))))break;++br}}}function l(){var e=pr.charCodeAt(br+1);return e>=48&&57>=e?E(!0):(++br,i(gt))}function f(){var e=pr.charCodeAt(br+1);return Er?(++br,k()):61===e?x(Ct,2):x(kt,1)}function p(){var e=pr.charCodeAt(br+1);return 61===e?x(Ct,2):x(Ot,1)}function d(e){var r=pr.charCodeAt(br+1);return r===e?x(124===e?It:Lt,2):61===r?x(Ct,2):x(124===e?Ut:Tt,1)}function m(){var e=pr.charCodeAt(br+1);return 61===e?x(Ct,2):x(Rt,1)}function h(e){var r=pr.charCodeAt(br+1);return r===e?x(At,2):61===r?x(Ct,2):x(Et,1)}function v(e){var r=pr.charCodeAt(br+1),t=1;return r===e?(t=62===e&&62===pr.charCodeAt(br+2)?3:2,61===pr.charCodeAt(br+t)?x(Ct,t+1):x(Ft,t)):(61===r&&(t=61===pr.charCodeAt(br+2)?3:2),x(qt,t))}function b(e){var r=pr.charCodeAt(br+1);return 61===r?x(Vt,61===pr.charCodeAt(br+2)?3:2):x(61===e?wt:St,1)}function y(e){switch(e){case 46:return l();case 40:return++br,i(mt);case 41:return++br,i(ht);case 59:return++br,i(bt);case 44:return++br,i(vt);case 91:return++br,i(lt);case 93:return++br,i(ft);case 123:return++br,i(pt);case 125:return++br,i(dt);case 58:return++br,i(yt);case 63:return++br,i(xt);case 48:var r=pr.charCodeAt(br+1);if(120===r||88===r)return C();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return E(!1);case 34:case 39:return A(e);case 47:return f(e);case 37:case 42:return p();case 124:case 38:return d(e);case 94:return m();case 43:case 45:return h(e);case 60:case 62:return v(e);case 61:case 33:return b(e);case 126:return x(St,1)}return!1}function g(e){if(e?br=yr+1:yr=br,fr.locations&&(xr=new a),e)return k();if(br>=dr)return i(Dr);var r=pr.charCodeAt(br);if(Qt(r)||92===r)return L();var n=y(r);if(n===!1){var o=String.fromCharCode(r);if("\\"===o||$t.test(o))return L();t(br,"Unexpected character '"+o+"'")}return n}function x(e,r){var t=pr.slice(br,br+r);br+=r,i(e,t)}function k(){for(var e,r,n="",a=br;;){br>=dr&&t(a,"Unterminated regular expression");var o=pr.charAt(br);if(Ht.test(o)&&t(a,"Unterminated regular expression"),e)e=!1;else{if("["===o)r=!0;else if("]"===o&&r)r=!1;else if("/"===o&&!r)break;e="\\"===o}++br}var n=pr.slice(a,br);++br;var s=I();return s&&!/^[gmsiy]*$/.test(s)&&t(a,"Invalid regexp flag"),i(Fr,RegExp(n,s))}function w(e,r){for(var t=br,n=0,a=0,o=null==r?1/0:r;o>a;++a){var i,s=pr.charCodeAt(br);if(i=s>=97?s-97+10:s>=65?s-65+10:s>=48&&57>=s?s-48:1/0,i>=e)break;++br,n=n*e+i}return br===t||null!=r&&br-t!==r?null:n}function C(){br+=2;var e=w(16);return null==e&&t(yr+2,"Expected hexadecimal number"),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number"),i(qr,e)}function E(e){var r=br,n=!1,a=48===pr.charCodeAt(br);e||null!==w(10)||t(r,"Invalid number"),46===pr.charCodeAt(br)&&(++br,w(10),n=!0);var o=pr.charCodeAt(br);(69===o||101===o)&&(o=pr.charCodeAt(++br),(43===o||45===o)&&++br,null===w(10)&&t(r,"Invalid number"),n=!0),Qt(pr.charCodeAt(br))&&t(br,"Identifier directly after number");var s,c=pr.slice(r,br);return n?s=parseFloat(c):a&&1!==c.length?/[89]/.test(c)||Vr?t(r,"Invalid number"):s=parseInt(c,8):s=parseInt(c,10),i(qr,s)}function A(e){br++;for(var r="";;){br>=dr&&t(yr,"Unterminated string constant");var n=pr.charCodeAt(br);if(n===e)return++br,i(Or,r);if(92===n){n=pr.charCodeAt(++br);var a=/^[0-7]+/.exec(pr.slice(br,br+3));for(a&&(a=a[0]);a&&parseInt(a,8)>255;)a=a.slice(0,a.length-1);if("0"===a&&(a=null),++br,a)Vr&&t(br-2,"Octal literal in strict mode"),r+=String.fromCharCode(parseInt(a,8)),br+=a.length-1;else switch(n){case 110:r+="\n";break;case 114:r+="\r";break;case 120:r+=String.fromCharCode(S(2));break;case 117:r+=String.fromCharCode(S(4));break;case 85:r+=String.fromCharCode(S(8));break;case 116:r+="	";break;case 98:r+="\b";break;case 118:r+="";break;case 102:r+="\f";break;case 48:r+="\0";break;case 13:10===pr.charCodeAt(br)&&++br;case 10:fr.locations&&(Sr=br,++Ar);break;default:r+=String.fromCharCode(n)}}else(13===n||10===n||8232===n||8329===n)&&t(yr,"Unterminated string constant"),r+=String.fromCharCode(n),++br}}function S(e){var r=w(16,e);return null===r&&t(yr,"Bad character escape sequence"),r}function I(){Dt=!1;for(var e,r=!0,n=br;;){var a=pr.charCodeAt(br);if(Yt(a))Dt&&(e+=pr.charAt(br)),++br;else{if(92!==a)break;Dt||(e=pr.slice(n,br)),Dt=!0,117!=pr.charCodeAt(++br)&&t(br,"Expecting Unicode escape sequence \\uXXXX"),++br;var o=S(4),i=String.fromCharCode(o);i||t(br-1,"Invalid Unicode escape"),(r?Qt(o):Yt(o))||t(br-4,"Invalid Unicode escape"),e+=i}r=!1}return Dt?e:pr.slice(n,br)}function L(){var e=I(),r=jr;return Dt||(Nt(e)?r=ut[e]:(fr.forbidReserved&&(3===fr.ecmaVersion?Bt:Mt)(e)||Vr&&zt(e))&&t(yr,"The keyword '"+e+"' is reserved")),i(r,e)}function U(){Ir=yr,Lr=gr,Ur=kr,g()}function R(e){for(Vr=e,br=Lr;Sr>br;)Sr=pr.lastIndexOf("\n",Sr-2)+1,--Ar;u(),g()}function T(){this.type=null,this.start=yr,this.end=null}function V(){this.start=xr,this.end=null,null!==mr&&(this.source=mr)}function q(){var e=new T;return fr.locations&&(e.loc=new V),fr.ranges&&(e.range=[yr,0]),e}function F(e){var r=new T;return r.start=e.start,fr.locations&&(r.loc=new V,r.loc.start=e.loc.start),fr.ranges&&(r.range=[e.range[0],0]),r}function O(e,r){return e.type=r,e.end=Lr,fr.locations&&(e.loc.end=Ur),fr.ranges&&(e.range[1]=Lr),e}function j(e){return fr.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.value}function D(e){return wr===e?(U(),!0):void 0}function B(){return!fr.strictSemicolons&&(wr===Dr||wr===dt||Ht.test(pr.slice(Lr,yr)))}function M(){D(bt)||B()||X()}function z(e){wr===e?U():X()}function X(){t(yr,"Unexpected token")}function N(e){"Identifier"!==e.type&&"MemberExpression"!==e.type&&t(e.start,"Assigning to rvalue"),Vr&&"Identifier"===e.type&&Xt(e.name)&&t(e.start,"Assigning to "+e.name+" in strict mode")}function W(e){Ir=Lr=br,fr.locations&&(Ur=new a),Rr=Vr=null,Tr=[],g();var r=e||q(),t=!0;for(e||(r.body=[]);wr!==Dr;){var n=J();r.body.push(n),t&&j(n)&&R(!0),t=!1}return O(r,"Program")}function J(){wr===kt&&g(!0);var e=wr,r=q();switch(e){case Br:case Xr:U();var n=e===Br;D(bt)||B()?r.label=null:wr!==jr?X():(r.label=lr(),M());for(var a=0;Tr.length>a;++a){var o=Tr[a];if(null==r.label||o.name===r.label.name){if(null!=o.kind&&(n||"loop"===o.kind))break;if(r.label&&n)break}}return a===Tr.length&&t(r.start,"Unsyntactic "+e.keyword),O(r,n?"BreakStatement":"ContinueStatement");case Nr:return U(),M(),O(r,"DebuggerStatement");case Jr:return U(),Tr.push(Zt),r.body=J(),Tr.pop(),z(rt),r.test=P(),M(),O(r,"DoWhileStatement");case Gr:if(U(),Tr.push(Zt),z(mt),wr===bt)return G(r,null);if(wr===et){var i=q();return U(),K(i,!0),1===i.declarations.length&&D(ct)?H(r,i):G(r,i)}var i=Q(!1,!0);return D(ct)?(N(i),H(r,i)):G(r,i);case Hr:return U(),cr(r,!0);case Kr:return U(),r.test=P(),r.consequent=J(),r.alternate=D(Pr)?J():null,O(r,"IfStatement");case Qr:return Rr||t(yr,"'return' outside of function"),U(),D(bt)||B()?r.argument=null:(r.argument=Q(),M()),O(r,"ReturnStatement");case Yr:U(),r.discriminant=P(),r.cases=[],z(pt),Tr.push(_t);for(var s,c;wr!=dt;)if(wr===Mr||wr===Wr){var u=wr===Mr;s&&O(s,"SwitchCase"),r.cases.push(s=q()),s.consequent=[],U(),u?s.test=Q():(c&&t(Ir,"Multiple default clauses"),c=!0,s.test=null),z(yt)}else s||X(),s.consequent.push(J());return s&&O(s,"SwitchCase"),U(),Tr.pop(),O(r,"SwitchStatement");case Zr:return U(),Ht.test(pr.slice(Lr,yr))&&t(Lr,"Illegal newline after throw"),r.argument=Q(),M(),O(r,"ThrowStatement");case _r:if(U(),r.block=$(),r.handler=null,wr===zr){var l=q();U(),z(mt),l.param=lr(),Vr&&Xt(l.param.name)&&t(l.param.start,"Binding "+l.param.name+" in strict mode"),z(ht),l.guard=null,l.body=$(),r.handler=O(l,"CatchClause")}return r.finalizer=D($r)?$():null,r.handler||r.finalizer||t(r.start,"Missing catch or finally clause"),O(r,"TryStatement");case et:return U(),r=K(r),M(),r;case rt:return U(),r.test=P(),Tr.push(Zt),r.body=J(),Tr.pop(),O(r,"WhileStatement");case tt:return Vr&&t(yr,"'with' in strict mode"),U(),r.object=P(),r.body=J(),O(r,"WithStatement");case pt:return $();case bt:return U(),O(r,"EmptyStatement");default:var f=Cr,p=Q();if(e===jr&&"Identifier"===p.type&&D(yt)){for(var a=0;Tr.length>a;++a)Tr[a].name===f&&t(p.start,"Label '"+f+"' is already declared");var d=wr.isLoop?"loop":wr===Yr?"switch":null;return Tr.push({name:f,kind:d}),r.body=J(),Tr.pop(),r.label=p,O(r,"LabeledStatement")}return r.expression=p,M(),O(r,"ExpressionStatement")}}function P(){z(mt);var e=Q();return z(ht),e}function $(){var e,r=q(),t=!0,n=!1;for(r.body=[],z(pt);!D(dt);){var a=J();r.body.push(a),t&&j(a)&&(e=n,R(n=!0)),t=!1}return n&&!e&&R(!1),O(r,"BlockStatement")}function G(e,r){return e.init=r,z(bt),e.test=wr===bt?null:Q(),z(bt),e.update=wr===ht?null:Q(),z(ht),e.body=J(),Tr.pop(),O(e,"ForStatement")}function H(e,r){return e.left=r,e.right=Q(),z(ht),e.body=J(),Tr.pop(),O(e,"ForInStatement")}function K(e,r){for(e.declarations=[],e.kind="var";;){var n=q();if(n.id=lr(),Vr&&Xt(n.id.name)&&t(n.id.start,"Binding "+n.id.name+" in strict mode"),n.init=D(wt)?Q(!0,r):null,e.declarations.push(O(n,"VariableDeclarator")),!D(vt))break}return O(e,"VariableDeclaration")}function Q(e,r){var t=Y(r);if(!e&&wr===vt){var n=F(t);for(n.expressions=[t];D(vt);)n.expressions.push(Y(r));return O(n,"SequenceExpression")}return t}function Y(e){var r=Z(e);if(wr.isAssign){var t=F(r);return t.operator=Cr,t.left=r,U(),t.right=Y(e),N(r),O(t,"AssignmentExpression")}return r}function Z(e){var r=_(e);if(D(xt)){var t=F(r);return t.test=r,t.consequent=Q(!0),z(yt),t.alternate=Q(!0,e),O(t,"ConditionalExpression")}return r}function _(e){return er(rr(e),-1,e)}function er(e,r,t){var n=wr.binop;if(null!=n&&(!t||wr!==ct)&&n>r){var a=F(e);a.left=e,a.operator=Cr,U(),a.right=er(rr(t),n,t);var a=O(a,/&&|\|\|/.test(a.operator)?"LogicalExpression":"BinaryExpression");return er(a,r,t)}return e}function rr(e){if(wr.prefix){var r=q(),n=wr.isUpdate;return r.operator=Cr,r.prefix=!0,U(),r.argument=rr(e),n?N(r.argument):Vr&&"delete"===r.operator&&"Identifier"===r.argument.type&&t(r.start,"Deleting local variable in strict mode"),O(r,n?"UpdateExpression":"UnaryExpression")}for(var a=tr();wr.postfix&&!B();){var r=F(a);r.operator=Cr,r.prefix=!1,r.argument=a,N(a),U(),a=O(r,"UpdateExpression")}return a}function tr(){return nr(ar())}function nr(e,r){if(D(gt)){var t=F(e);return t.object=e,t.property=lr(!0),t.computed=!1,nr(O(t,"MemberExpression"),r)}if(D(lt)){var t=F(e);return t.object=e,t.property=Q(),t.computed=!0,z(ft),nr(O(t,"MemberExpression"),r)}if(!r&&D(mt)){var t=F(e);return t.callee=e,t.arguments=ur(ht,!1),nr(O(t,"CallExpression"),r)}return e}function ar(){switch(wr){case at:var e=q();return U(),O(e,"ThisExpression");case jr:return lr();case qr:case Or:case Fr:var e=q();return e.value=Cr,e.raw=pr.slice(yr,gr),U(),O(e,"Literal");case ot:case it:case st:var e=q();return e.value=wr.atomValue,e.raw=wr.keyword,U(),O(e,"Literal");case mt:var r=xr,t=yr;U();var n=Q();return n.start=t,n.end=gr,fr.locations&&(n.loc.start=r,n.loc.end=kr),fr.ranges&&(n.range=[t,gr]),z(ht),n;case lt:var e=q();return U(),e.elements=ur(ft,!0,!0),O(e,"ArrayExpression");case pt:return ir();case Hr:var e=q();return U(),cr(e,!1);case nt:return or();default:X()}}function or(){var e=q();return U(),e.callee=nr(ar(),!0),e.arguments=D(mt)?ur(ht,!1):[],O(e,"NewExpression")}function ir(){var e=q(),r=!0,n=!1;for(e.properties=[],U();!D(dt);){if(r)r=!1;else if(z(vt),fr.allowTrailingCommas&&D(dt))break;var a,o={key:sr()},i=!1;if(D(yt)?(o.value=Q(!0),a=o.kind="init"):fr.ecmaVersion>=5&&"Identifier"===o.key.type&&("get"===o.key.name||"set"===o.key.name)?(i=n=!0,a=o.kind=o.key.name,o.key=sr(),wr!==mt&&X(),o.value=cr(q(),!1)):X(),"Identifier"===o.key.type&&(Vr||n))for(var s=0;e.properties.length>s;++s){var c=e.properties[s];if(c.key.name===o.key.name){var u=a==c.kind||i&&"init"===c.kind||"init"===a&&("get"===c.kind||"set"===c.kind);u&&!Vr&&"init"===a&&"init"===c.kind&&(u=!1),u&&t(o.key.start,"Redefinition of property")}}e.properties.push(o)}return O(e,"ObjectExpression")}function sr(){return wr===qr||wr===Or?ar():lr(!0)}function cr(e,r){wr===jr?e.id=lr():r?X():e.id=null,e.params=[];var n=!0;for(z(mt);!D(ht);)n?n=!1:z(vt),e.params.push(lr());var a=Rr,o=Tr;if(Rr=!0,Tr=[],e.body=$(!0),Rr=a,Tr=o,Vr||e.body.body.length&&j(e.body.body[0]))for(var i=e.id?-1:0;e.params.length>i;++i){var s=0>i?e.id:e.params[i];if((zt(s.name)||Xt(s.name))&&t(s.start,"Defining '"+s.name+"' in strict mode"),i>=0)for(var c=0;i>c;++c)s.name===e.params[c].name&&t(s.start,"Argument name clash in strict mode")}return O(e,r?"FunctionDeclaration":"FunctionExpression")}function ur(e,r,t){for(var n=[],a=!0;!D(e);){if(a)a=!1;else if(z(vt),r&&fr.allowTrailingCommas&&D(e))break;t&&wr===vt?n.push(null):n.push(Q(!0))}return n}function lr(e){var r=q();return r.name=wr===jr?Cr:e&&!fr.forbidReserved&&wr.keyword||X(),U(),O(r,"Identifier")}e.version="0.2.01";var fr,pr,dr,mr;e.parse=function(e,t){return pr=e+"",dr=pr.length,r(t),o(),W(fr.program)};var hr=e.defaultOptions={ecmaVersion:5,strictSemicolons:!1,allowTrailingCommas:!0,forbidReserved:!1,locations:!1,onComment:null,ranges:!1,program:null,sourceFile:null},vr=e.getLineInfo=function(e,r){for(var t=1,n=0;;){Kt.lastIndex=n;var a=Kt.exec(e);if(!(a&&r>a.index))break;++t,n=a.index+a[0].length}return{line:t,column:r-n}};e.tokenize=function(e,t){function n(e){return g(e),a.start=yr,a.end=gr,a.startLoc=xr,a.endLoc=kr,a.type=wr,a.value=Cr,a}pr=e+"",dr=pr.length,r(t),o();var a={};return n.jumpTo=function(e,r){if(br=e,fr.locations){Ar=Sr=Kt.lastIndex=0;for(var t;(t=Kt.exec(pr))&&e>t.index;)++Ar,Sr=t.index+t[0].length}pr.charAt(e-1),Er=r,u()},n};var br,yr,gr,xr,kr,wr,Cr,Er,Ar,Sr,Ir,Lr,Ur,Rr,Tr,Vr,qr={type:"num"},Fr={type:"regexp"},Or={type:"string"},jr={type:"name"},Dr={type:"eof"},Br={keyword:"break"},Mr={keyword:"case",beforeExpr:!0},zr={keyword:"catch"},Xr={keyword:"continue"},Nr={keyword:"debugger"},Wr={keyword:"default"},Jr={keyword:"do",isLoop:!0},Pr={keyword:"else",beforeExpr:!0},$r={keyword:"finally"},Gr={keyword:"for",isLoop:!0},Hr={keyword:"function"},Kr={keyword:"if"},Qr={keyword:"return",beforeExpr:!0},Yr={keyword:"switch"},Zr={keyword:"throw",beforeExpr:!0},_r={keyword:"try"},et={keyword:"var"},rt={keyword:"while",isLoop:!0},tt={keyword:"with"},nt={keyword:"new",beforeExpr:!0},at={keyword:"this"},ot={keyword:"null",atomValue:null},it={keyword:"true",atomValue:!0},st={keyword:"false",atomValue:!1},ct={keyword:"in",binop:7,beforeExpr:!0},ut={"break":Br,"case":Mr,"catch":zr,"continue":Xr,"debugger":Nr,"default":Wr,"do":Jr,"else":Pr,"finally":$r,"for":Gr,"function":Hr,"if":Kr,"return":Qr,"switch":Yr,"throw":Zr,"try":_r,"var":et,"while":rt,"with":tt,"null":ot,"true":it,"false":st,"new":nt,"in":ct,"instanceof":{keyword:"instanceof",binop:7,beforeExpr:!0},"this":at,"typeof":{keyword:"typeof",prefix:!0,beforeExpr:!0},"void":{keyword:"void",prefix:!0,beforeExpr:!0},"delete":{keyword:"delete",prefix:!0,beforeExpr:!0}},lt={type:"[",beforeExpr:!0},ft={type:"]"},pt={type:"{",beforeExpr:!0},dt={type:"}"},mt={type:"(",beforeExpr:!0},ht={type:")"},vt={type:",",beforeExpr:!0},bt={type:";",beforeExpr:!0},yt={type:":",beforeExpr:!0},gt={type:"."},xt={type:"?",beforeExpr:!0},kt={binop:10,beforeExpr:!0},wt={isAssign:!0,beforeExpr:!0},Ct={isAssign:!0,beforeExpr:!0},Et={binop:9,prefix:!0,beforeExpr:!0},At={postfix:!0,prefix:!0,isUpdate:!0},St={prefix:!0,beforeExpr:!0},It={binop:1,beforeExpr:!0},Lt={binop:2,beforeExpr:!0},Ut={binop:3,beforeExpr:!0},Rt={binop:4,beforeExpr:!0},Tt={binop:5,beforeExpr:!0},Vt={binop:6,beforeExpr:!0},qt={binop:7,beforeExpr:!0},Ft={binop:8,beforeExpr:!0},Ot={binop:10,beforeExpr:!0};e.tokTypes={bracketL:lt,bracketR:ft,braceL:pt,braceR:dt,parenL:mt,parenR:ht,comma:vt,semi:bt,colon:yt,dot:gt,question:xt,slash:kt,eq:wt,name:jr,eof:Dr,num:qr,regexp:Fr,string:Or};for(var jt in ut)e.tokTypes[jt]=ut[jt];var Dt,Bt=n("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),Mt=n("class enum extends super const export import"),zt=n("implements interface let package private protected public static yield"),Xt=n("eval arguments"),Nt=n("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"),Wt=/[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/,Jt="\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",Pt="\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f",$t=RegExp("["+Jt+"]"),Gt=RegExp("["+Jt+Pt+"]"),Ht=/[\n\r\u2028\u2029]/,Kt=/\r\n|[\n\r\u2028\u2029]/g,Qt=e.isIdentifierStart=function(e){return 65>e?36===e:91>e?!0:97>e?95===e:123>e?!0:e>=170&&$t.test(String.fromCharCode(e))},Yt=e.isIdentifierChar=function(e){return 48>e?36===e:58>e?!0:65>e?!1:91>e?!0:97>e?95===e:123>e?!0:e>=170&&Gt.test(String.fromCharCode(e))},Zt={kind:"loop"},_t={kind:"switch"}});
\ No newline at end of file
diff --git a/lib/acorn.js b/lib/acorn.js
index 7b3b48b0..c9c540df 100644
--- a/lib/acorn.js
+++ b/lib/acorn.js
@@ -29,7 +29,7 @@
 
   exports.version = "0.2.01";
 
-  // The main exported interface (under `this.acorn` when in the
+  // The main exported interface (under `self.acorn` when in the
   // browser) is a `parse` function that takes a code string and
   // returns an abstract syntax tree as specified by [Mozilla parser
   // API][api], with the caveat that the SpiderMonkey-specific syntax
@@ -407,7 +407,7 @@
 
   var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/;
   var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
-  var nonASCIIidentifierChars = "\u0371-\u0374\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
+  var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
   var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
   var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
 
@@ -1716,4 +1716,4 @@
     return finishNode(node, "Identifier");
   }
 
-});
+});
\ No newline at end of file
diff --git a/lib/straps.js b/lib/straps.js
index ec487570..5fe27e28 100755
--- a/lib/straps.js
+++ b/lib/straps.js
@@ -1,36 +1,31 @@
 /**
- * Straps.js - Inheritance library with support for bean-style accessors and
- * AOP patterns.
+ * straps.js - Class inheritance library with support for bean-style accessors
  *
  * Copyright (c) 2006 - 2013 Juerg Lehni
  * http://lehni.org/
  *
  * Distributed under the MIT license.
  *
- * straps.js was created by extracting and simplifying the inheritance code from
- * boostrap.js, a JavaScript DOM library, also published by Juerg Lehni:
+ * straps.js was created by extracting and simplifying the inheritance framework
+ * from boostrap.js, a JavaScript DOM library, also published by Juerg Lehni:
  * https://github.com/lehni/bootstrap.js
- * The name was changed due to Twitter's introduction of their CSS framework
- * with the same name.
  *
  * Inspirations:
  * http://dean.edwards.name/weblog/2006/03/base/
  * http://dev.helma.org/Wiki/JavaScript+Inheritance+Sugar/
  */
 
-var Base = this.Base = new function() { // Straps scope
+var Base = new function() {
 	var hidden = /^(statics|generics|preserve|enumerable|prototype|toString|valueOf)$/,
-		proto = Object.prototype,
-		toString = proto.toString,
+		toString = Object.prototype.toString,
 		proto = Array.prototype,
-		isArray = Array.isArray = Array.isArray || function(obj) {
-			return toString.call(obj) === '[object Array]';
-		},
 		slice = proto.slice,
+
 		forEach = proto.forEach || function(iter, bind) {
 			for (var i = 0, l = this.length; i < l; i++)
 				iter.call(bind, this[i], i, this);
 		},
+
 		forIn = function(iter, bind) {
 			// Do not use Object.keys for iteration as iterators might modify
 			// the object we're iterating over, making the hasOwnProperty still
@@ -39,52 +34,54 @@ var Base = this.Base = new function() { // Straps scope
 				if (this.hasOwnProperty(i))
 					iter.call(bind, this[i], i, this);
 		},
-		// A ahort cut to a simplified version of Object.create that only
+
+		isArray = Array.isArray = Array.isArray || function(obj) {
+			return toString.call(obj) === '[object Array]';
+		},
+
+		// A short-cut to a simplified version of Object.create that only
 		// supports the first parameter (in the emulation):
 		create = Object.create || function(proto) {
 			// From all browsers that do not offer Object.create(), we only
-			// support Firefox 3.5 & 3.5, and this hack works there:
+			// support Firefox 3.5 & 3.6, and this hack works there:
 			return { __proto__: proto };
 		},
-		_define = Object.defineProperty,
-		_describe = Object.getOwnPropertyDescriptor;
 
-	// Support a mixed environment of some ECMAScript 5 features present,
-	// along with __defineGetter/Setter__ functions, as found in browsers today.
-	function define(obj, name, desc) {
-		// Unfortunately Safari seems to ignore configurable: true and
-		// does not override existing properties, so we need to delete
-		// first:
-		if (_define) {
-			try {
-				delete obj[name];
-				return _define(obj, name, desc);
-			} catch (e) {}
-		}
-		if ((desc.get || desc.set) && obj.__defineGetter__) {
-			if (desc.get) obj.__defineGetter__(name, desc.get);
-			if (desc.set) obj.__defineSetter__(name, desc.set);
-		} else {
-			obj[name] = desc.value;
-		}
-		return obj;
-	}
+		describe = Object.getOwnPropertyDescriptor || function(obj, name) {
+			// Emulate Object.getOwnPropertyDescriptor for outdated browsers
+			var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
+			return get
+					? { get: get, set: obj.__lookupSetter__(name),
+						enumerable: true, configurable: true }
+					: obj.hasOwnProperty(name)
+						? { value: obj[name], enumerable: true,
+							configurable: true, writable: true }
+						: null;
+		},
 
-	function describe(obj, name) {
-		if (_describe) {
-			try {
-				return _describe(obj, name);
-			} catch (e) {}
-		}
-		var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
-		return get
-			? { get: get, set: obj.__lookupSetter__(name), enumerable: true,
-					configurable: true }
-			: obj.hasOwnProperty(name)
-				? { value: obj[name], enumerable: true, configurable: true,
-						writable: true }
-				: null;
-	}
+		_define = Object.defineProperty || function(obj, name, desc) {
+			// Emulate Object.defineProperty for outdated browsers
+			if ((desc.get || desc.set) && obj.__defineGetter__) {
+				if (desc.get)
+					obj.__defineGetter__(name, desc.get);
+				if (desc.set)
+					obj.__defineSetter__(name, desc.set);
+			} else {
+				obj[name] = desc.value;
+			}
+			return obj;
+		},
+
+		define = function(obj, name, desc) {
+			// Both Safari and Chrome at one point ignored configurable = true
+			// and did not allow overriding of existing properties:
+			// https://code.google.com/p/chromium/issues/detail?id=72736
+			// https://bugs.webkit.org/show_bug.cgi?id=54289
+			// The workaround is to delete the property first.
+			// TODO: Remove this fix in July 2014, and use _define directly.
+			delete obj[name];
+			return _define(obj, name, desc);
+		};
 
 	/**
 	 * Private function that injects functions from src into dest, overriding
@@ -109,58 +106,34 @@ var Base = this.Base = new function() { // Straps scope
 			// string values starting with '#'
 			if (typeof val === 'string' && val[0] === '#')
 				val = src[val.substring(1)] || val;
-			var func = typeof val === 'function',
+			var isFunc = typeof val === 'function',
 				res = val,
 				// Only lookup previous value if we preserve or define a
 				// function that might need it for this.base(). If we're
 				// defining a getter, don't lookup previous value, but look if
 				// the property exists (name in dest) and store result in prev
-				prev = preserve || func
+				prev = preserve || isFunc
 					? (val && val.get ? name in dest : dest[name]) : null;
 			if ((dontCheck || val !== undefined && src.hasOwnProperty(name))
 					&& (!preserve || !prev)) {
-				if (func) {
-					if (prev && /\bthis\.base\b/.test(val)) {
-						var fromBase = base && base[name] == prev;
-						res = function() {
-							// Look up the base function each time if we can,
-							// to reflect changes to the base class after
-							// inheritance.
-							var tmp = describe(this, 'base');
-							define(this, 'base', { value: fromBase
-								? base[name] : prev, configurable: true });
-							try {
-								return val.apply(this, arguments);
-							} finally {
-								tmp ? define(this, 'base', tmp)
-									: delete this.base;
-							}
-						};
-						// Make wrapping closure pretend to be the original
-						// function on inspection
-						res.toString = function() {
-							return val.toString();
-						};
-						res.valueOf = function() {
-							return val.valueOf();
-						};
-					}
-					// Produce bean properties if getters are specified. This
-					// does not produce properties for setter-only properties.
-					// Just collect beans for now, and look them up in dest at
-					// the end of fields injection. This ensures this.base()
-					// works in beans too, and inherits setters for redefined
-					// getters in subclasses. Only add getter beans if they do
-					// not expect arguments. Functions that should function both
-					// with optional arguments and as beans should not declare
-					// the parameters and use the arguments array internally
-					// instead.
-					if (beans && val.length === 0
-							&& (bean = name.match(/^(get|is)(([A-Z])(.*))$/)))
-						beans.push([ bean[3].toLowerCase() + bean[4], bean[2] ]);
-				}
+				// Expose the 'super' function (meaning the one this function is
+				// overriding) through #base:
+				if (isFunc && prev)
+					val.base = prev;
+				// Produce bean properties if getters are specified. This does
+				// not produce properties for setter-only properties. Just
+				// collect beans for now, and look them up in dest at the end of
+				// fields injection. This ensures base works for beans too, and
+				// inherits setters for redefined getters in subclasses. Only
+				// add getter beans if they do not expect arguments. Functions
+				// that should function both with optional arguments and as
+				// beans should not declare the parameters and use the arguments
+				// array internally instead.
+				if (isFunc && beans && val.length === 0
+						&& (bean = name.match(/^(get|is)(([A-Z])(.*))$/)))
+					beans.push([ bean[3].toLowerCase() + bean[4], bean[2] ]);
 				// No need to look up getter if this is a function already.
-				if (!res || func || !res.get)
+				if (!res || isFunc || !res.get)
 					res = { value: res, writable: true };
 				// Only set/change configurable and enumerable if this field is
 				// configurable
@@ -171,7 +144,7 @@ var Base = this.Base = new function() { // Straps scope
 				}
 				define(dest, name, res);
 			}
-			if (generics && func && (!preserve || !generics[name])) {
+			if (generics && isFunc && (!preserve || !generics[name])) {
 				generics[name] = function(bind) {
 					// Do not call Array.slice generic here, as on Safari,
 					// this seems to confuse scopes (calling another
@@ -210,10 +183,11 @@ var Base = this.Base = new function() { // Straps scope
 	function each(obj, iter, bind, asArray) {
 		try {
 			if (obj)
-				(asArray || asArray === undefined && isArray(obj)
+				(asArray || typeof asArray === 'undefined' && isArray(obj)
 					? forEach : forIn).call(obj, iter, bind = bind || obj);
 		} catch (e) {
-			if (e !== Base.stop) throw e;
+			if (e !== Base.stop)
+				throw e;
 		}
 		return bind;
 	}
@@ -225,7 +199,8 @@ var Base = this.Base = new function() { // Straps scope
 	}
 
 	// Inject into new ctor object that's passed to inject(), and then returned
-	return inject(function() {}, {
+	// as the Base class.
+	return inject(function Base() {}, {
 		inject: function(src/*, ... */) {
 			if (src) {
 				var proto = this.prototype,
@@ -252,16 +227,19 @@ var Base = this.Base = new function() { // Straps scope
 		},
 
 		extend: function(src/* , ... */) {
-			var ctor = function() {
-				// Call the constructor function, if defined
-				if (this.initialize)
-					return this.initialize.apply(this, arguments);
+			var base = this,
+				ctor;
+			// Look for an initialize function in all injection objects and use
+			// it directly as the actual constructor.
+			for (var i = 0, l = arguments.length; i < l; i++)
+				if (ctor = arguments[i].initialize)
+					break;
+			// If no initialize function is provided, create a constructor that
+			// simply calls the base constructor.
+			ctor = ctor || function() {
+				base.apply(this, arguments);
 			};
 			ctor.prototype = create(this.prototype);
-			// Add a toString function that delegates to initialize if possible
-			ctor.toString = function() {
-				return (this.prototype.initialize || function() {}).toString();
-			};
 			// The new prototype extends the constructor on which extend is
 			// called. Fix constructor.
 			define(ctor.prototype, 'constructor',
@@ -320,8 +298,8 @@ var Base = this.Base = new function() { // Straps scope
 			define: define,
 			describe: describe,
 
-			// Base.create does something different from Object.create, it only
-			// works on constructors and uses their prototype.
+			// Base.create does something different from Object.create:
+			// It works on constructors and uses their prototype.
 			create: function(ctor) {
 				return create(ctor.prototype);
 			},
@@ -331,10 +309,12 @@ var Base = this.Base = new function() { // Straps scope
 			 * plain Base object, as produced by Base.merge().
 			 */
 			isPlainObject: function(obj) {
-				var proto = obj !== null && typeof obj === 'object'
-						&& Object.getPrototypeOf(obj);
-				return proto && (proto === Object.prototype
-						|| proto === Base.prototype);
+				var ctor = obj != null && obj.constructor;
+				// We also need to check for ctor.name === 'Object', in case
+				// this is an object from another global scope (e.g. an iframe,
+				// or another vm context in node.js).
+				return ctor && (ctor === Object || ctor === Base
+						|| ctor.name === 'Object');
 			},
 
 			check: function(obj) {
@@ -342,9 +322,8 @@ var Base = this.Base = new function() { // Straps scope
 			},
 
 			/**
-			 * Returns the first argument that is defined.
-			 * Null is counted as defined too, since !== undefined is used for
-			 * comparisons. In this it differs from Mootools!
+			 * Returns the first argument that is defined. null is counted as
+			 * defined too, as !== undefined is used for comparisons.
 			 */
 			pick: function() {
 				for (var i = 0, l = arguments.length; i < l; i++)
@@ -354,13 +333,10 @@ var Base = this.Base = new function() { // Straps scope
 			},
 
 			/**
-			 * A special constant, to be thrown by closures passed to each()
+			 * Base.stop can be thrown by iterators passed to each()
 			 *
-			 * $continue / Base.next is not implemented, as the same
-			 * functionality can achieved by using return in the closure.
-			 * In prototype, the implementation of $continue also leads to a
-			 * huge speed decrease, as the closure is wrapped in another closure
-			 * that does nothing else than handling $continue.
+			 * continue (Base.next) is not implemented, as the same can achieved
+			 * by using return in the iterator.
 			 */
 			stop: {}
 		}
diff --git a/package.json b/package.json
index 9d102c4b..e7e33684 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "paper",
-	"version": "0.8.3",
+	"version": "0.9.0",
 	"main": "./src/node/index.js",
 	"engines": { "node": ">= 0.4.0" },
 	"dependencies": {
diff --git a/src/basic/Line.js b/src/basic/Line.js
index 9070bd6a..6002f77f 100644
--- a/src/basic/Line.js
+++ b/src/basic/Line.js
@@ -15,32 +15,33 @@
  *
  * @class The Line object represents..
  */
-var Line = this.Line = Base.extend(/** @lends Line# */{
+var Line = Base.extend(/** @lends Line# */{
 	// DOCS: document Line class and constructor
 	/**
 	 * Creates a Line object.
 	 *
 	 * @param {Point} point1
 	 * @param {Point} point2
-	 * @param {Boolean} [infinite=true]
+	 * @param {Boolean} [asVector=false]
 	 */
-	initialize: function(point1, point2, infinite) {
-		// Convention: With 3 parameters, both points are absolute, and infinite
-		// controls wether the line extends beyond the defining points, meaning
-		// intersection outside the line segment are allowed.
-		// With two parameters, the 2nd parameter is a direction, and infinite
-		// is automatially true, since we're describing an infinite line.
-		var _point1 = Point.read(arguments),
-			_point2 = Point.read(arguments),
-			_infinite = Base.read(arguments);
-		if (_infinite !== undefined) {
-			this.point = _point1;
-			this.vector = _point2.subtract(_point1);
-			this.infinite = _infinite;
+	initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
+		var asVector = false;
+		if (arguments.length >= 4) {
+			this._px = arg0;
+			this._py = arg1;
+			this._vx = arg2;
+			this._vy = arg3;
+			asVector = arg4;
 		} else {
-			this.point = _point1;
-			this.vector = _point2;
-			this.infinite = true;
+			this._px = arg0.x;
+			this._py = arg0.y;
+			this._vx = arg1.x;
+			this._vy = arg1.y;
+			asVector = arg2;
+		}
+		if (!asVector) {
+			this._vx -= this._px;
+			this._vy -= this._py;
 		}
 	},
 
@@ -50,6 +51,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
 	 * @name Line#point
 	 * @type Point
 	 */
+	getPoint: function() {
+		return new Point(this._px, this._py);
+	},
 
 	/**
 	 * The vector of the line
@@ -57,33 +61,21 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
 	 * @name Line#vector
 	 * @type Point
 	 */
-
-	/**
-	 * Specifies whether the line extends infinitely
-	 *
-	 * @name Line#infinite
-	 * @type Boolean
-	 */
+	getVector: function() {
+		return new Point(this._vx, this._vy);
+	},
 
 	/**
 	 * @param {Line} line
+	 * @param {Boolean} [isInfinite=false]
 	 * @return {Point} the intersection point of the lines, {@code undefined}
 	 * if the two lines are colinear, or {@code null} if they don't intersect.
 	 */
-	intersect: function(line) {
-		var cross = this.vector.cross(line.vector);
-		// Avoid divisions by 0, and errors when getting too close to 0
-		if (Numerical.isZero(cross))
-			return undefined;
-		var v = line.point.subtract(this.point),
-			t1 = v.cross(line.vector) / cross,
-			t2 = v.cross(this.vector) / cross;
-		// Check the ranges of t parameters if the line is not allowed to
-		// extend beyond the definition points.
-		return (this.infinite || 0 <= t1 && t1 <= 1)
-				&& (line.infinite || 0 <= t2 && t2 <= 1)
-			? this.point.add(this.vector.multiply(t1))
-			: null;
+	intersect: function(line, isInfinite) {
+		return Line.intersect(
+				this._px, this._py, this._vx, this._vy,
+				line._px, line._py, line._vx, line._vy,
+				true, isInfinite);
 	},
 
 	// DOCS: document Line#getSide(point)
@@ -92,18 +84,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
 	 * @return {Number}
 	 */
 	getSide: function(point) {
-		var v1 = this.vector,
-			v2 = point.subtract(this.point),
-			ccw = v2.cross(v1);
-		if (ccw === 0) {
-			ccw = v2.dot(v1);
-			if (ccw > 0) {
-				ccw = v2.subtract(v1).dot(v1);
-				if (ccw < 0)
-				    ccw = 0;
-			}
-		}
-		return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
+		return Line.getSide(
+				this._px, this._py, this._vx, this._vy,
+				point.x, point.y, true);
 	},
 
 	// DOCS: document Line#getDistance(point)
@@ -112,33 +95,70 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
 	 * @return {Number}
 	 */
 	getDistance: function(point) {
-		var m = this.vector.y / this.vector.x, // slope
-			b = this.point.y - (m * this.point.x); // y offset
-		// Distance to the linear equation
-		var dist = Math.abs(point.y - (m * point.x) - b) / Math.sqrt(m * m + 1);
-		return this.infinite ? dist : Math.min(dist,
-				point.getDistance(this.point),
-				point.getDistance(this.point.add(this.vector)));
+		return Math.abs(Line.getSignedDistance(
+				this._px, this._py, this._vx, this._vy,
+				point.x, point.y, true));
 	},
 
-	statics: {
-		intersect: function(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, infinite) {
-			var adx = ax2 - ax1,
-				ady = ay2 - ay1,
-				bdx = bx2 - bx1,
-				bdy = by2 - by1,
-				dx = ax1 - bx1,
-				dy = ay1 - by1,
-				cross = bdy * adx - bdx * ady;
-			if (!Numerical.isZero(cross)) {
-				var ta = (bdx * dy - bdy * dx) / cross,
-					tb = (adx * dy - ady * dx) / cross;
-					if ((infinite || 0 <= ta && ta <= 1)
-							&& (infinite || 0 <= tb && tb <= 1))
-						return Point.create(
-									ax1 + ta * adx,
-									ay1 + ta * ady);
+	statics: /** @lends Line */{
+		intersect: function(apx, apy, avx, avy, bpx, bpy, bvx, bvy, asVector,
+				isInfinite) {
+			// Convert 2nd points to vectors if they are not specified as such.
+			if (!asVector) {
+				avx -= apx;
+				avy -= apy;
+				bvx -= bpx;
+				bvy -= bpy;
 			}
+			var cross = bvy * avx - bvx * avy;
+			// Avoid divisions by 0, and errors when getting too close to 0
+			if (!Numerical.isZero(cross)) {
+				var dx = apx - bpx,
+					dy = apy - bpy,
+					ta = (bvx * dy - bvy * dx) / cross,
+					tb = (avx * dy - avy * dx) / cross;
+				// Check the ranges of t parameters if the line is not allowed
+				// to extend beyond the definition points.
+				if ((isInfinite || 0 <= ta && ta <= 1)
+						&& (isInfinite || 0 <= tb && tb <= 1))
+					return new Point(
+								apx + ta * avx,
+								apy + ta * avy);
+			}
+		},
+
+		getSide: function(px, py, vx, vy, x, y, asVector) {
+			if (!asVector) {
+				vx -= px;
+				vy -= py;
+			}
+			var v2x = x - px,
+				v2y = y - py,
+				ccw = v2x * vy - v2y * vx; // ccw = v2.cross(v1);
+			if (ccw === 0) {
+				ccw = v2x * vx + v2y * vy; // ccw = v2.dot(v1);
+				if (ccw > 0) {
+					// ccw = v2.subtract(v1).dot(v1);
+					v2x -= vx;
+					v2y -= vy;
+					ccw = v2x * vx + v2y * vy;
+					if (ccw < 0)
+						ccw = 0;
+				}
+			}
+			return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
+		},
+
+		getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
+			if (!asVector) {
+				vx -= px;
+				vy -= py;
+			}
+			// Cache these values since they're used heavily in fatline code
+			var m = vy / vx, // slope
+				b = py - m * px; // y offset
+			// Distance to the linear equation
+			return (y - (m * x) - b) / Math.sqrt(m * m + 1);
 		}
 	}
 });
diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js
index f472927f..c5d83e49 100644
--- a/src/basic/Matrix.js
+++ b/src/basic/Matrix.js
@@ -37,9 +37,7 @@
  * knowledge of the underlying matrix (as opposed to say simply performing
  * matrix multiplication).
  */
-var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
-	_class: 'Matrix',
-
+var Matrix = Base.extend(/** @lends Matrix# */{
 	/**
 	 * Creates a 2D affine transform.
 	 *
@@ -50,7 +48,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
 	 * @param {Number} tx The translateX coordinate of the transform
 	 * @param {Number} ty The translateY coordinate of the transform
 	 */
-	initialize: function(arg) {
+	initialize: function Matrix(arg) {
 		var count = arguments.length,
 			ok = true;
 		if (count == 6) {
@@ -101,7 +99,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
 	 * @return {Matrix} A copy of this transform.
 	 */
 	clone: function() {
-		return Matrix.create(this._a, this._c, this._b, this._d,
+		return new Matrix(this._a, this._c, this._b, this._d,
 				this._tx, this._ty);
 	},
 
@@ -518,7 +516,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
 
 		return {
 			translation: this.getTranslation(),
-			scaling: Point.create(scaleX, scaleY),
+			scaling: new Point(scaleX, scaleY),
 			rotation: -Math.atan2(b, a) * 180 / Math.PI,
 			shearing: shear
 		};
@@ -585,7 +583,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
 	 */
 	getTranslation: function() {
 		// No decomposition is required to extract translation, so treat this
-		return Point.create(this._tx, this._ty);
+		return new Point(this._tx, this._ty);
 	},
 
 	/**
@@ -620,7 +618,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
 	 */
 	inverted: function() {
 		var det = this._getDeterminant();
-		return det && Matrix.create(
+		return det && new Matrix(
 				this._d / det,
 				-this._c / det,
 				-this._b / det,
@@ -630,7 +628,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
 	},
 
 	shiftless: function() {
-		return Matrix.create(this._a, this._c, this._b, this._d, 0, 0);
+		return new Matrix(this._a, this._c, this._b, this._d, 0, 0);
 	},
 
 	/**
@@ -640,13 +638,6 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
 	 */
 	applyToContext: function(ctx) {
 		ctx.transform(this._a, this._c, this._b, this._d, this._tx, this._ty);
-	},
-
-	statics: /** @lends Matrix */{
-		// See Point.create()
-		create: function(a, c, b, d, tx, ty) {
-			return Base.create(Matrix).set(a, c, b, d, tx, ty);
-		}
 	}
 }, new function() {
 	return Base.each({
diff --git a/src/basic/Point.js b/src/basic/Point.js
index ed8c0ab5..bb9f5216 100644
--- a/src/basic/Point.js
+++ b/src/basic/Point.js
@@ -23,8 +23,7 @@
  * console.log(point.x); // 10
  * console.log(point.y); // 5
  */
-var Point = this.Point = Base.extend(/** @lends Point# */{
-	_class: 'Point',
+var Point = Base.extend(/** @lends Point# */{
 	// Tell Base.read that the Point constructor supports reading with index
 	_readIndex: true,
 
@@ -129,7 +128,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	 * @param {Point} point
 	 * @name Point#initialize
 	 */
-	initialize: function(arg0, arg1) {
+	initialize: function Point(arg0, arg1) {
 		var type = typeof arg0;
 		if (type === 'number') {
 			var hasY = typeof arg1 === 'number';
@@ -217,7 +216,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	 * @returns {Point} the cloned point
 	 */
 	clone: function() {
-		return Point.create(this.x, this.y);
+		return new Point(this.x, this.y);
 	},
 
 	/**
@@ -269,7 +268,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	 */
 	add: function(point) {
 		point = Point.read(arguments);
-		return Point.create(this.x + point.x, this.y + point.y);
+		return new Point(this.x + point.x, this.y + point.y);
 	},
 
 	/**
@@ -305,7 +304,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	 */
 	subtract: function(point) {
 		point = Point.read(arguments);
-		return Point.create(this.x - point.x, this.y - point.y);
+		return new Point(this.x - point.x, this.y - point.y);
 	},
 
 	/**
@@ -341,7 +340,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	 */
 	multiply: function(point) {
 		point = Point.read(arguments);
-		return Point.create(this.x * point.x, this.y * point.y);
+		return new Point(this.x * point.x, this.y * point.y);
 	},
 
 	/**
@@ -377,7 +376,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	 */
 	divide: function(point) {
 		point = Point.read(arguments);
-		return Point.create(this.x / point.x, this.y / point.y);
+		return new Point(this.x / point.x, this.y / point.y);
 	},
 
 	/**
@@ -410,11 +409,11 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	 */
 	modulo: function(point) {
 		point = Point.read(arguments);
-		return Point.create(this.x % point.x, this.y % point.y);
+		return new Point(this.x % point.x, this.y % point.y);
 	},
 
 	negate: function() {
-		return Point.create(-this.x, -this.y);
+		return new Point(-this.x, -this.y);
 	},
 
 	/**
@@ -501,7 +500,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 			length = 1;
 		var current = this.getLength(),
 			scale = current != 0 ? length / current : 0,
-			point = Point.create(this.x * scale, this.y * scale);
+			point = new Point(this.x * scale, this.y * scale);
 		// Preserve angle.
 		point._angle = this._angle;
 		return point;
@@ -650,7 +649,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 		var point = center ? this.subtract(center) : this,
 			s = Math.sin(angle),
 			c = Math.cos(angle);
-		point = Point.create(
+		point = new Point(
 			point.x * c - point.y * s,
 			point.y * c + point.x * s
 		);
@@ -754,10 +753,10 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	project: function(point) {
 		point = Point.read(arguments);
 		if (point.isZero()) {
-			return Point.create(0, 0);
+			return new Point(0, 0);
 		} else {
 			var scale = this.dot(point) / point.dot(point);
-			return Point.create(
+			return new Point(
 				point.x * scale,
 				point.y * scale
 			);
@@ -775,23 +774,6 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	 */
 
 	statics: /** @lends Point */{
-		/**
-		 * Provide a faster creator for Points out of two coordinates that
-		 * does not rely on Point#initialize at all. This speeds up all math
-		 * operations a lot.
-		 *
-		 * @ignore
-		 */
-		create: function(x, y) {
-			// Don't use the shorter form as we want absolute maximum
-			// performance here:
-			// return Base.create(Point).set(x, y);
-			var point = Base.create(Point);
-			point.x = x;
-			point.y = y;
-			return point;
-		},
-
 		/**
 		 * Returns a new point object with the smallest {@link #x} and
 		 * {@link #y} of the supplied points.
@@ -810,7 +792,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 		min: function(point1, point2) {
 			var _point1 = Point.read(arguments);
 				_point2 = Point.read(arguments);
-			return Point.create(
+			return new Point(
 				Math.min(_point1.x, _point2.x),
 				Math.min(_point1.y, _point2.y)
 			);
@@ -834,7 +816,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 		max: function(point1, point2) {
 			var _point1 = Point.read(arguments);
 				_point2 = Point.read(arguments);
-			return Point.create(
+			return new Point(
 				Math.max(_point1.x, _point2.x),
 				Math.max(_point1.y, _point2.y)
 			);
@@ -855,7 +837,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 		 * var point = maxPoint * randomPoint;
 		 */
 		random: function() {
-			return Point.create(Math.random(), Math.random());
+			return new Point(Math.random(), Math.random());
 		}
 	}
 }, new function() { // Scope for injecting round, ceil, floor, abs:
@@ -922,7 +904,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
 	return Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
 		var op = Math[name];
 		this[name] = function() {
-			return Point.create(op(this.x), op(this.y));
+			return new Point(op(this.x), op(this.y));
 		};
 	}, {});
 });
@@ -970,7 +952,7 @@ var LinkedPoint = Point.extend({
 			// through an optional parameter that can be passed to the getters.
 			// See e.g. Rectangle#getPoint(true).
 			if (dontLink)
-				return Point.create(x, y);
+				return new Point(x, y);
 			var point = Base.create(LinkedPoint);
 			point._x = x;
 			point._y = y;
diff --git a/src/basic/Rectangle.js b/src/basic/Rectangle.js
index dd64ac61..36a7516d 100644
--- a/src/basic/Rectangle.js
+++ b/src/basic/Rectangle.js
@@ -17,8 +17,7 @@
  * point (x, y), its width, and its height. It should not be confused with a
  * rectangular path, it is not an item.
  */
-var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
-	_class: 'Rectangle',
+var Rectangle = Base.extend(/** @lends Rectangle# */{
 	// Tell Base.read that the Rectangle constructor supports reading with index
 	_readIndex: true,
 
@@ -72,7 +71,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
 	 * @name Rectangle#initialize
 	 * @param {Rectangle} rt
 	 */
-	initialize: function(arg0, arg1, arg2, arg3) {
+	initialize: function Rectangle(arg0, arg1, arg2, arg3) {
 		var type = typeof arg0,
 			read = 0;
 		if (type === 'number') {
@@ -191,7 +190,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
 	 * Returns a copy of the rectangle.
 	 */
 	clone: function() {
-		return Rectangle.create(this.x, this.y, this.width, this.height);
+		return new Rectangle(this.x, this.y, this.width, this.height);
 	},
 
 	/**
@@ -652,7 +651,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
 			y1 = Math.max(this.y, rect.y),
 			x2 = Math.min(this.x + this.width, rect.x + rect.width),
 			y2 = Math.min(this.y + this.height, rect.y + rect.height);
-		return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
 	},
 
 	/**
@@ -669,7 +668,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
 			y1 = Math.min(this.y, rect.y),
 			x2 = Math.max(this.x + this.width, rect.x + rect.width),
 			y2 = Math.max(this.y + this.height, rect.y + rect.height);
-		return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
 	},
 
 	/**
@@ -692,7 +691,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
 			y1 = Math.min(this.y, point.y),
 			x2 = Math.max(this.x + this.width, point.x),
 			y2 = Math.max(this.y + this.height, point.y);
-		return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
 	},
 
 	/**
@@ -716,7 +715,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
 	expand: function(hor, ver) {
 		if (ver === undefined)
 			ver = hor;
-		return Rectangle.create(this.x - hor / 2, this.y - ver / 2,
+		return new Rectangle(this.x - hor / 2, this.y - ver / 2,
 				this.width + hor, this.height + ver);
 	},
 
@@ -740,13 +739,6 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
 	scale: function(hor, ver) {
 		return this.expand(this.width * hor - this.width,
 				this.height * (ver === undefined ? hor : ver) - this.height);
-	},
-
-	statics: {
-		// See Point.create()
-		create: function(x, y, width, height) {
-			return Base.create(Rectangle).set(x, y, width, height);
-		}
 	}
 }, new function() {
 	return Base.each([
diff --git a/src/basic/Size.js b/src/basic/Size.js
index 10dc970f..3981630b 100644
--- a/src/basic/Size.js
+++ b/src/basic/Size.js
@@ -22,8 +22,7 @@
  * console.log(size.width); // 10
  * console.log(size.height); // 5
  */
-var Size = this.Size = Base.extend(/** @lends Size# */{
-	_class: 'Size',
+var Size = Base.extend(/** @lends Size# */{
 	// Tell Base.read that the Point constructor supports reading with index
 	_readIndex: true,
 
@@ -90,7 +89,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	 * console.log(size.width); // 50
 	 * console.log(size.height); // 50
 	 */
-	initialize: function(arg0, arg1) {
+	initialize: function Size(arg0, arg1) {
 		var type = typeof arg0;
 		if (type === 'number') {
 			var hasHeight = typeof arg1 === 'number';
@@ -164,7 +163,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	 * Returns a copy of the size.
 	 */
 	clone: function() {
-		return Size.create(this.width, this.height);
+		return new Size(this.width, this.height);
 	},
 
 	/**
@@ -214,7 +213,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	 */
 	add: function(size) {
 		size = Size.read(arguments);
-		return Size.create(this.width + size.width, this.height + size.height);
+		return new Size(this.width + size.width, this.height + size.height);
 	},
 
 	/**
@@ -249,7 +248,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	 */
 	subtract: function(size) {
 		size = Size.read(arguments);
-		return Size.create(this.width - size.width, this.height - size.height);
+		return new Size(this.width - size.width, this.height - size.height);
 	},
 
 	/**
@@ -283,7 +282,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	 */
 	multiply: function(size) {
 		size = Size.read(arguments);
-		return Size.create(this.width * size.width, this.height * size.height);
+		return new Size(this.width * size.width, this.height * size.height);
 	},
 
 	/**
@@ -317,7 +316,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	 */
 	divide: function(size) {
 		size = Size.read(arguments);
-		return Size.create(this.width / size.width, this.height / size.height);
+		return new Size(this.width / size.width, this.height / size.height);
 	},
 
 	/**
@@ -350,11 +349,11 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	 */
 	modulo: function(size) {
 		size = Size.read(arguments);
-		return Size.create(this.width % size.width, this.height % size.height);
+		return new Size(this.width % size.width, this.height % size.height);
 	},
 
 	negate: function() {
-		return Size.create(-this.width, -this.height);
+		return new Size(-this.width, -this.height);
 	},
 
 	/**
@@ -377,11 +376,6 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	},
 
 	statics: /** @lends Size */{
-		// See Point.create()
-		create: function(width, height) {
-			return Base.create(Size).set(width, height);
-		},
-
 		/**
 		 * Returns a new size object with the smallest {@link #width} and
 		 * {@link #height} of the supplied sizes.
@@ -398,7 +392,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 		 * console.log(minSize); // {width: 10, height: 5}
 		 */
 		min: function(size1, size2) {
-			return Size.create(
+			return new Size(
 				Math.min(size1.width, size2.width),
 				Math.min(size1.height, size2.height));
 		},
@@ -419,7 +413,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 		 * console.log(maxSize); // {width: 200, height: 100}
 		 */
 		max: function(size1, size2) {
-			return Size.create(
+			return new Size(
 				Math.max(size1.width, size2.width),
 				Math.max(size1.height, size2.height));
 		},
@@ -437,7 +431,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 		 * var size = maxSize * randomSize;
 		 */
 		random: function() {
-			return Size.create(Math.random(), Math.random());
+			return new Size(Math.random(), Math.random());
 		}
 	}
 }, new function() { // Scope for injecting round, ceil, floor, abs:
@@ -505,7 +499,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
 	return Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
 		var op = Math[name];
 		this[name] = function() {
-			return Size.create(op(this.width), op(this.height));
+			return new Size(op(this.width), op(this.height));
 		};
 	}, {});
 });
@@ -551,7 +545,7 @@ var LinkedSize = Size.extend({
 		create: function(owner, setter, width, height, dontLink) {
 			// See LinkedPoint.create() for an explanation about dontLink.
 			if (dontLink)
-				return Size.create(width, height);
+				return new Size(width, height);
 			var size = Base.create(LinkedSize);
 			size._width = width;
 			size._height = height;
diff --git a/src/canvas/CanvasProvider.js b/src/canvas/CanvasProvider.js
index 4b9c6b03..91ad5b09 100644
--- a/src/canvas/CanvasProvider.js
+++ b/src/canvas/CanvasProvider.js
@@ -16,7 +16,7 @@ var CanvasProvider = {
 	canvases: [],
 
 	getCanvas: function(width, height) {
-		var size = height === undefined ? width : Size.create(width, height);
+		var size = height === undefined ? width : new Size(width, height);
 		if (this.canvases.length) {
 			var canvas = this.canvases.pop();
 			// If they are not the same size, we don't need to clear them
diff --git a/src/core/Base.js b/src/core/Base.js
index 6093ae47..bed032bd 100644
--- a/src/core/Base.js
+++ b/src/core/Base.js
@@ -17,7 +17,7 @@
  */
 // Extend Base with utility functions used across the library. Also set
 // this.Base on the injection scope, since straps.js ommits that.
-this.Base = Base.inject(/** @lends Base# */{
+Base.inject(/** @lends Base# */{
 	// Have generics versions of #clone() and #toString():
 	generics: true,
 
@@ -36,7 +36,7 @@ this.Base = Base.inject(/** @lends Base# */{
 	 */
 	toString: function() {
 		return this._id != null
-			?  (this._class || 'Object') + (this._name
+			?  (this.constructor.name || 'Object') + (this._name
 				? " '" + this._name + "'"
 				: ' @' + this._id)
 			: '{ ' + Base.each(this, function(value, key) {
@@ -80,15 +80,17 @@ this.Base = Base.inject(/** @lends Base# */{
 
 	statics: /** @lends Base */{
 
-		_classes: {},
+		// Keep track of all named classes for serialization and exporting.
+		// Also register the Base class itself.
+		exports: new Base({ Base: Base }),
 
-		extend: function(src) {
-			// Override Base.extend() with a version that registers classes that
-			// define #_class inside the Base._classes lookup, for
-			// deserialization.
-			var res = this.base.apply(this, arguments);
-			if (src._class)
-				Base._classes[src._class] = res;
+		extend: function extend(src) {
+			// Override Base.extend() to register named classes in Base.exports,
+			// for deserialization and injection into PaperScope.
+			var res = extend.base.apply(this, arguments),
+				name = res.name;
+			if (name)
+				Base.exports[name] = res;
 			return res;
 		},
 
@@ -289,11 +291,12 @@ this.Base = Base.inject(/** @lends Base# */{
 							ref = this.references[id];
 						if (!ref) {
 							this.length++;
-							var res = create.call(item);
+							var res = create.call(item),
+								name = item.constructor.name;
 							// Also automatically insert class for dictionary
 							// entries.
-							if (item._class && res[0] !== item._class)
-								res.unshift(item._class);
+							if (name && res[0] !== name)
+								res.unshift(name);
 							this.definitions[id] = res;
 							ref = this.references[id] = [id];
 						}
@@ -306,13 +309,18 @@ this.Base = Base.inject(/** @lends Base# */{
 				// If we don't serialize to compact form (meaning no type
 				// identifier), see if _serialize didn't already add the class,
 				// e.g. for classes that do not support compact form.
-				if (obj._class && !compact && res[0] !== obj._class)
-					res.unshift(obj._class);
+				var name = obj.constructor.name;
+				if (name && !compact && !res._compact && res[0] !== name)
+					res.unshift(name);
 			} else if (Array.isArray(obj)) {
 				res = [];
 				for (var i = 0, l = obj.length; i < l; i++)
 					res[i] = Base.serialize(obj[i], options, compact,
 							dictionary);
+				// Mark array as compact, so obj._serialize handling above
+				// doesn't add the constructor name again.
+				if (compact)
+					res._compact = true;
 			} else if (Base.isPlainObject(obj)) {
 				res = {};
 				for (var i in obj)
@@ -332,7 +340,7 @@ this.Base = Base.inject(/** @lends Base# */{
 		/**
 		 * Deserializes from parsed JSON data. A simple convention is followed:
 		 * Array values with a string at the first position are links to
-		 * deserializable types through Base._classes, and the values following
+		 * deserializable types through Base.exports, and the values following
 		 * in the array are the arguments to their initialize function.
 		 * Any other value is passed on unmodified.
 		 * The passed data is recoursively traversed and converted, leaves first
@@ -356,7 +364,7 @@ this.Base = Base.inject(/** @lends Base# */{
 					// if so return its definition instead.
 					if (data.dictionary && obj.length == 1 && /^#/.test(type))
 						return data.dictionary[type];
-					type = Base._classes[type];
+					type = Base.exports[type];
 				}
 				res = [];
 				// Skip first type entry for arguments
diff --git a/src/core/Callback.js b/src/core/Callback.js
index 55ccd429..676a04c4 100644
--- a/src/core/Callback.js
+++ b/src/core/Callback.js
@@ -98,7 +98,7 @@ var Callback = {
 	statics: {
 		// Override inject() so that sub-classes automatically add the accessors
 		// for the event handler functions (e.g. #onMouseDown) for each property
-		inject: function(/* src, ... */) {
+		inject: function inject(/* src, ... */) {
 			for (var i = 0, l = arguments.length; i < l; i++) {
 				var src = arguments[i],
 					events = src._events;
@@ -132,7 +132,7 @@ var Callback = {
 					});
 					src._eventTypes = types;
 				}
-				this.base(src);
+				inject.base.call(this, src);
 			}
 			return this;
 		}
diff --git a/src/core/PaperScope.js b/src/core/PaperScope.js
index 9b25183c..c2d8f00b 100644
--- a/src/core/PaperScope.js
+++ b/src/core/PaperScope.js
@@ -32,7 +32,7 @@
  * The global {@link paper} object is simply a reference to the currently active
  * {@code PaperScope}.
  */
-var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{
+var PaperScope = Base.extend(/** @lends PaperScope# */{
 
 	/**
 	 * Creates a PaperScope object.
@@ -40,7 +40,7 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{
 	 * @name PaperScope#initialize
 	 * @function
 	 */
-	initialize: function(script) {
+	initialize: function PaperScope(script) {
 		// script is only used internally, when creating scopes for PaperScript.
 		// Whenever a PaperScope is created, it automatically becomes the active
 		// one.
@@ -71,11 +71,11 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{
 	},
 
 	/**
-	 * The version of Paper.js, as a float number.
+	 * The version of Paper.js, as a string.
 	 *
-	 * @type Number
+	 * @type String
 	 */
-	version: /*#=*/ options.version,
+	version: '/*#=*/ options.version',
 
 	/**
 	 * The currently active project.
@@ -139,7 +139,6 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{
 		Base.each(['project', 'view', 'tool'], function(key) {
 			Base.define(scope, key, {
 				configurable: true,
-				writable: true,
 				get: function() {
 					return that[key];
 				}
diff --git a/src/core/PaperScript.js b/src/core/PaperScript.js
index 427d38fb..2e362cf9 100644
--- a/src/core/PaperScript.js
+++ b/src/core/PaperScript.js
@@ -20,8 +20,8 @@
 /*#*/ } else if (options.parser == 'esprima') {
 /*#*/ include('../../lib/esprima-min.js');
 /*#*/ }
-
-var PaperScript = this.PaperScript = new function() {
+ 
+var PaperScript = new function() {
 	// Operators to overload
 
 	var binaryOperators = {
diff --git a/src/core/initialize.js b/src/core/initialize.js
deleted file mode 100644
index ca05a307..00000000
--- a/src/core/initialize.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
- * http://paperjs.org/
- *
- * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
- * http://lehni.org/ & http://jonathanpuckey.com/
- *
- * Distributed under the MIT license. See LICENSE file for details.
- *
- * All rights reserved.
- */
-
-/*#*/ if (options.version == 'dev') {
-// When in dev mode, also export all classes through PaperScope, to mimick
-// scoping behavior of the built library.
-Base.each(this, function(val, key) {
-	if (val && val.prototype instanceof Base || val === Base)
-		PaperScope.prototype[key] = val;
-});
-// See paper.js for the non-dev version of this code. We cannot handle dev there
-// due to the seperate loading of all source files, which are only availabe
-// after the execution of paper.js
-var paper = new PaperScope();
-/*#*/ } // options.version == 'dev'
diff --git a/src/dom/DomElement.js b/src/dom/DomElement.js
index 4e5c1a46..60d665c4 100644
--- a/src/dom/DomElement.js
+++ b/src/dom/DomElement.js
@@ -158,7 +158,7 @@ var DomElement = new function() {
 			var doc = el.ownerDocument,
 				view = doc.defaultView,
 				html = doc.documentElement;
-			return Rectangle.create(0, 0, 
+			return new Rectangle(0, 0, 
 				view.innerWidth || html.clientWidth,
 				view.innerHeight || html.clientHeight
 			);
diff --git a/src/dom/DomEvent.js b/src/dom/DomEvent.js
index f2877636..8183dab0 100644
--- a/src/dom/DomEvent.js
+++ b/src/dom/DomEvent.js
@@ -49,7 +49,7 @@ var DomEvent = {
 					? event.targetTouches[0]
 					: event.changedTouches[0]
 				: event;
-		return Point.create(
+		return new Point(
 			pos.pageX || pos.clientX + document.documentElement.scrollLeft,
 			pos.pageY || pos.clientY + document.documentElement.scrollTop
 		);
diff --git a/src/export.js b/src/export.js
new file mode 100644
index 00000000..d18df8bc
--- /dev/null
+++ b/src/export.js
@@ -0,0 +1,18 @@
+/*
+ * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
+ * http://paperjs.org/
+ *
+ * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
+ * http://lehni.org/ & http://jonathanpuckey.com/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * All rights reserved.
+ */
+
+// Add PaperScript and Numerical to exports, inject all exports into PaperScope,
+// and create the initial paper object, all in one condensed statement:
+var paper = new (PaperScope.inject(Base.exports.inject({
+	PaperScript: PaperScript,
+	Numerical: Numerical
+})))();
diff --git a/src/item/Clip.js b/src/item/Clip.js
index a311f223..f6061fa5 100644
--- a/src/item/Clip.js
+++ b/src/item/Clip.js
@@ -20,7 +20,10 @@
  *
  * @extends Group
  */
-var Clip = this.Clip = Group.extend(/** @lends Clip# */{
-	_class: 'Clip',
-	_applyMatrix: false
+var Clip = Group.extend(/** @lends Clip# */{
+	_applyMatrix: false,
+
+	initialize: function Clip() {
+		Group.apply(this, arguments);
+	}
 });
diff --git a/src/item/Group.js b/src/item/Group.js
index 6e42c04f..509eda70 100644
--- a/src/item/Group.js
+++ b/src/item/Group.js
@@ -19,8 +19,7 @@
  *
  * @extends Item
  */
-var Group = this.Group = Item.extend(/** @lends Group# */{
-	_class: 'Group',
+var Group = Item.extend(/** @lends Group# */{
 	_serializeFields: {
 		children: []
 	},
@@ -88,8 +87,8 @@ var Group = this.Group = Item.extend(/** @lends Group# */{
 	 * 	position: view.center
 	 * });
 	 */
-	initialize: function(arg) {
-		this.base();
+	initialize: function Group(arg) {
+		Item.call(this);
 		// Allow Group to have children and named children
 		this._children = [];
 		this._namedChildren = {};
@@ -97,9 +96,12 @@ var Group = this.Group = Item.extend(/** @lends Group# */{
 			this.addChildren(Array.isArray(arg) ? arg : arguments);
 	},
 
-	_changed: function(flags) {
-		// Don't use this.base() for reasons of performance.
-		Item.prototype._changed.call(this, flags);
+	_changed: function _changed(flags) {
+		_changed.base.call(this, flags);
+		if (flags & /*#=*/ ChangeFlag.HIERARCHY && !this._matrix.isIdentity()) {
+			// Apply matrix now that we have content.
+			this.applyMatrix();
+		}
 		if (flags & (/*#=*/ ChangeFlag.HIERARCHY | /*#=*/ ChangeFlag.CLIPPING)) {
 			// Clear cached clip item whenever hierarchy changes
 			delete this._clipItem;
diff --git a/src/item/HitResult.js b/src/item/HitResult.js
index bf4f4e82..2bcc9ee5 100644
--- a/src/item/HitResult.js
+++ b/src/item/HitResult.js
@@ -17,8 +17,8 @@
  * test. It is returned by {@link Item#hitTest(point)} and
  * {@link Project#hitTest(point)}.
  */
-var HitResult = this.HitResult = Base.extend(/** @lends HitResult# */{
-	initialize: function(type, item, values) {
+var HitResult = Base.extend(/** @lends HitResult# */{
+	initialize: function HitResult(type, item, values) {
 		this.type = type;
 		this.item = item;
 		// Inject passed values, so we can be flexible about the HitResult
diff --git a/src/item/Item.js b/src/item/Item.js
index 021d29c3..ecb3d159 100644
--- a/src/item/Item.js
+++ b/src/item/Item.js
@@ -20,23 +20,27 @@
  * is unique to their type, but share the underlying properties and functions
  * that they inherit from Item.
  */
-var Item = this.Item = Base.extend(Callback, {
+var Item = Base.extend(Callback, /** @lends Item# */{
 	statics: {
 		/**
 		 * Override Item.extend() to merge the subclass' _serializeFields with
 		 * the parent class' _serializeFields.
+		 *
+		 * @private
 		 */
-		extend: function(src) {
+		extend: function extend(src) {
 			if (src._serializeFields)
 				src._serializeFields = Base.merge(
 						this.prototype._serializeFields, src._serializeFields);
-			// Derive the _type string from _class
-			if (src._class)
-				src._type = Base.hyphenate(src._class);
-			return this.base.apply(this, arguments);
+			var res = extend.base.apply(this, arguments),
+				name = res.name;
+			// Derive the _type string from constructor name
+			if (name)
+				res.prototype._type = Base.hyphenate(name);
+			return res;
 		}
-	}
-}, /** @lends Item# */{
+	},
+
 	// All items apply their matrix by default.
 	// Exceptions are Raster, PlacedSymbol, Clip and Shape.
 	_applyMatrix: true,
@@ -55,7 +59,7 @@ var Item = this.Item = Base.extend(Callback, {
 		data: {}
 	},
 
-	initialize: function(point) {
+	initialize: function Item(point) {
 		// Define this Item's unique id.
 		this._id = Item._id = (Item._id || 0) + 1;
 		// If _project is already set, the item was already moved into the DOM
@@ -168,7 +172,7 @@ var Item = this.Item = Base.extend(Callback, {
 			serialize(this._style._defaults);
 		// There is no compact form for Item serialization, we always keep the
 		// type.
-		return [ this._class, props ];
+		return [ this.constructor.name, props ];
 	},
 
 	/**
@@ -198,7 +202,7 @@ var Item = this.Item = Base.extend(Callback, {
 			this._clearBoundsCache();
 		}
 		if (flags & /*#=*/ ChangeFlag.APPEARANCE) {
-			this._project._needsRedraw();
+			this._project._needsRedraw = true;
 		}
 		// If this item is a symbol's definition, notify it of the change too
 		if (this._parentSymbol)
@@ -878,7 +882,7 @@ var Item = this.Item = Base.extend(Callback, {
 			}
 		}
 		return isFinite(x1)
-				? Rectangle.create(x1, y1, x2 - x1, y2 - y1)
+				? new Rectangle(x1, y1, x2 - x1, y2 - y1)
 				: new Rectangle();
 	},
 
@@ -1428,7 +1432,6 @@ var Item = this.Item = Base.extend(Callback, {
 	 * @param {Item} item The item to be added as a child
 	 */
 	addChild: function(item, _preserve) {
-		// Pass on internal _preserve boolean, for CompoundPath#insertChild
 		return this.insertChild(undefined, item, _preserve);
 	},
 
@@ -1441,21 +1444,8 @@ var Item = this.Item = Base.extend(Callback, {
 	 * @param {Item} item The item to be appended as a child
 	 */
 	insertChild: function(index, item, _preserve) {
-		// _preserve parameter is not used here, but CompoundPath#insertChild()
-		// needs it.
-		if (this._children) {
-			item._remove(true);
-			Base.splice(this._children, [item], index, 0);
-			item._parent = this;
-			item._setProject(this._project);
-			// Setting the name again makes sure all name lookup structures are
-			// kept in sync.
-			if (item._name)
-				item.setName(item._name);
-			this._changed(/*#=*/ Change.HIERARCHY);
-			return item;
-		}
-		return null;
+		var res = this.insertChildren(index, [item], _preserve);
+		return res && res[0];
 	},
 
 	/**
@@ -1477,25 +1467,42 @@ var Item = this.Item = Base.extend(Callback, {
 	 * @param {Number} index
 	 * @param {Item[]} items The items to be appended as children
 	 */
-	insertChildren: function(index, items, _preserve) {
-		// We need to clone items because it might be
-		// an Item#children array. Use Array.prototype.slice because
-		// in certain cases items is an arguments object
-		items = items && Array.prototype.slice.apply(items);
-		var children = this._children,
-			length = children.length,
-			i = index;
-		for (var j = 0, l = items && items.length; j < l; j++) {
-			if (this.insertChild(i, items[j], _preserve)) {
-				// We need to keep track of how much the list actually grows,
-				// bcause we might be removing and inserting into the same list,
-				// in which case the size would not chage.
-				var newLength = children.length;
-				i += newLength - length;
-				length = newLength;
+	insertChildren: function(index, items, _preserve, _type) {
+		// CompoundPath#insertChildren() requires _preserve and _type:
+		// _preserve avoids changing of the children's path orientation
+		// _type enforces the inserted type.
+		var children = this._children;
+		if (children && items && items.length > 0) {
+			// We need to clone items because it might be
+			// an Item#children array. Also, we're removing elements if they
+			// don't match _type. Use Array.prototype.slice becaus items can be
+			// an arguments object.
+			items = Array.prototype.slice.apply(items);
+			// Remove the items from their parents first, since they might be
+			// inserted into their own parents, affecting indices.
+			// Use the loop also to filter out wrong _type.
+			for (var i = items.length - 1; i >= 0; i--) {
+				var item = items[i];
+				if (_type && item._type !== _type)
+					items.splice(i, 1);
+				else
+					item._remove(true);
 			}
+			Base.splice(children, items, index, 0);
+			for (var i = 0, l = items.length; i < l; i++) {
+				var item = items[i];
+				item._parent = this;
+				item._setProject(this._project);
+				// Setting the name again makes sure all name lookup structures
+				// are kept in sync.
+				if (item._name)
+					item.setName(item._name);
+			}
+			this._changed(/*#=*/ Change.HIERARCHY);
+		} else {
+			items = null;
 		}
-		return i != index;
+		return items;
 	},
 
 	/**
@@ -2220,9 +2227,10 @@ var Item = this.Item = Base.extend(Callback, {
 	},
 
 	_transformContent: function(matrix, applyMatrix) {
-		if (this._children) {
-			for (var i = 0, l = this._children.length; i < l; i++)
-				this._children[i].transform(matrix, applyMatrix);
+		var children = this._children;
+		if (children && children.length > 0) {
+			for (var i = 0, l = children.length; i < l; i++)
+				children[i].transform(matrix, applyMatrix);
 			return true;
 		}
 	},
@@ -2332,7 +2340,7 @@ var Item = this.Item = Base.extend(Callback, {
 					? rectangle.width / bounds.width
 					: rectangle.height / bounds.height,
 			newBounds = new Rectangle(new Point(),
-					Size.create(bounds.width * scale, bounds.height * scale));
+					new Size(bounds.width * scale, bounds.height * scale));
 		newBounds.setCenter(rectangle.getCenter());
 		this.setBounds(newBounds);
 	},
@@ -2877,7 +2885,7 @@ var Item = this.Item = Base.extend(Callback, {
 			// so we draw onto it, instead of the parentCtx
 			parentCtx = ctx;
 			ctx = CanvasProvider.getContext(
-					bounds.getSize().ceil().add(Size.create(1, 1)));
+					bounds.getSize().ceil().add(new Size(1, 1)));
 		}
 		ctx.save();
 		// Translate the context so the topLeft of the item is at (0, 0)
diff --git a/src/item/Layer.js b/src/item/Layer.js
index ff2afaf0..6a9c85aa 100644
--- a/src/item/Layer.js
+++ b/src/item/Layer.js
@@ -22,8 +22,7 @@
  *
  * @extends Group
  */
-var Layer = this.Layer = Group.extend(/** @lends Layer# */{
-	_class: 'Layer',
+var Layer = Group.extend(/** @lends Layer# */{
 	// DOCS: improve constructor code example.
 	/**
 	 * Creates a new Layer item and places it at the end of the
@@ -57,11 +56,11 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
 	 * 	position: view.center
 	 * });
 	 */
-	initialize: function(items) {
+	initialize: function Layer(items) {
 		this._project = paper.project;
 		// Push it onto project.layers and set index:
 		this._index = this._project.layers.push(this) - 1;
-		this.base.apply(this, arguments);
+		Group.apply(this, arguments);
 		this.activate();
 	},
 
@@ -69,9 +68,9 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
 	* Removes the layer from its project's layers list
 	* or its parent's children list.
 	*/
-	_remove: function(notify) {
+	_remove: function _remove(notify) {
 		if (this._parent)
-			return this.base(notify);
+			return _remove.base.call(this, notify);
 		if (this._index != null) {
 			if (this._project.activeLayer === this)
 				this._project.activeLayer = this.getNextSibling()
@@ -79,24 +78,24 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
 			Base.splice(this._project.layers, null, this._index, 1);
 			// Tell project we need a redraw. This is similar to _changed()
 			// mechanism.
-			this._project._needsRedraw();
+			this._project._needsRedraw = true;
 			return true;
 		}
 		return false;
 	},
 
-	getNextSibling: function() {
-		return this._parent ? this.base()
+	getNextSibling: function getNextSibling() {		
+		return this._parent ? getNextSibling.base.call(this)
 				: this._project.layers[this._index + 1] || null;
 	},
 
-	getPreviousSibling: function() {
-		return this._parent ? this.base()
+	getPreviousSibling: function getPreviousSibling() {
+		return this._parent ? getPreviousSibling.base.call(this)
 				: this._project.layers[this._index - 1] || null;
 	},
 
-	isInserted: function() {
-		return this._parent ? this.base() : this._index != null;
+	isInserted: function isInserted() {
+		return this._parent ? isInserted.base.call(this) : this._index != null;
 	},
 
 	/**
@@ -114,7 +113,7 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
 	}
 }, new function () {
 	function insert(above) {
-		return function(item) {
+		return function insert(item) {
 			// If the item is a layer and contained within Project#layers, use
 			// our own version of move().
 			if (item instanceof Layer && !item._parent
@@ -124,7 +123,7 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
 				this._setProject(item._project);
 				return true;
 			}
-			return this.base(item);
+			return insert.base.call(this, item);
 		};
 	}
 
diff --git a/src/item/PlacedSymbol.js b/src/item/PlacedSymbol.js
index 06298ac2..08b5f189 100644
--- a/src/item/PlacedSymbol.js
+++ b/src/item/PlacedSymbol.js
@@ -18,8 +18,7 @@
  *
  * @extends Item
  */
-var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
-	_class: 'PlacedSymbol',
+var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
 	_applyMatrix: false,
 	// PlacedSymbol uses strokeBounds for bounds
 	_boundsGetter: { getBounds: 'getStrokeBounds' },
@@ -68,11 +67,11 @@ var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
 	 *     instance.scale(0.25 + Math.random() * 0.75);
 	 * }
 	 */
-	initialize: function(arg0, arg1) {
+	initialize: function PlacedSymbol(arg0, arg1) {
 		// Support two forms of item initialization: Passing one object literal
 		// describing all the different properties to be set, or a symbol (arg0)
 		// and a point where it should be placed (arg1).
-		this.base(arg1 !== undefined && Point.read(arguments, 1));
+		Item.call(this, arg1 !== undefined && Point.read(arguments, 1));
 		// If we can handle setting properties through object literal, we're all
 		// set. Otherwise we need to set symbol.
 		if (arg0 && !this._set(arg0))
diff --git a/src/item/Raster.js b/src/item/Raster.js
index 5899222f..63022136 100644
--- a/src/item/Raster.js
+++ b/src/item/Raster.js
@@ -17,8 +17,7 @@
  *
  * @extends Item
  */
-var Raster = this.Raster = Item.extend(/** @lends Raster# */{
-	_class: 'Raster',
+var Raster = Item.extend(/** @lends Raster# */{
 	_applyMatrix: false,
 	// Raster doesn't make the distinction between the different bounds,
 	// so use the same name for all of them
@@ -72,11 +71,11 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
 	 * raster.scale(0.5);
 	 * raster.rotate(10);
 	 */
-	initialize: function(object, position) {
+	initialize: function Raster(object, position) {
 		// Support two forms of item initialization: Passing one object literal
 		// describing all the different properties to be set, or an image
 		// (object) and a point where it should be placed (point).
-		this.base(position !== undefined && Point.read(arguments, 1));
+		Item.call(this, position !== undefined && Point.read(arguments, 1));
 		// If we can handle setting properties through object literal, we're all
 		// set. Otherwise we need to check the type of object:
 		if (object && !this._set(object)) {
@@ -164,7 +163,7 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
 			orig = new Point(0, 0).transform(matrix),
 			u = new Point(1, 0).transform(matrix).subtract(orig),
 			v = new Point(0, 1).transform(matrix).subtract(orig);
-		return Size.create(
+		return new Size(
 			72 / u.getLength(),
 			72 / v.getLength()
 		);
@@ -218,7 +217,7 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
 		if (this._canvas)
 			CanvasProvider.release(this._canvas);
 		this._canvas = canvas;
-		this._size = Size.create(canvas.width, canvas.height);
+		this._size = new Size(canvas.width, canvas.height);
 		this._image = null;
 		this._context = null;
 		this._changed(/*#=*/ Change.GEOMETRY | /*#=*/ Change.PIXELS);
@@ -239,10 +238,10 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
 			CanvasProvider.release(this._canvas);
 		this._image = image;
 /*#*/ if (options.browser) {
-		this._size = Size.create(image.naturalWidth, image.naturalHeight);
-/*#*/ } else if (options.server) {
-		this._size = Size.create(image.width, image.height);
-/*#*/ } // options.server
+		this._size = new Size(image.naturalWidth, image.naturalHeight);
+/*#*/ } else if (options.node) {
+		this._size = new Size(image.width, image.height);
+/*#*/ } // options.node
 		this._canvas = null;
 		this._context = null;
 		this._changed(/*#=*/ Change.GEOMETRY);
@@ -296,14 +295,22 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
 		} else if (!image.src) {
 			image.src = src;
 		}
-/*#*/ } else if (options.server) {
-		// If we're running on the server and it's a string,
-		// load it from disk:
-		// TODO: load images async, calling setImage once loaded as above
-		var image = new Image();
-		image.src = fs.readFileSync(src);
-/*#*/ } // options.server
 		this.setImage(image);
+/*#*/ } else if (options.node) {
+		var image = new Image();
+		// If we're running on the server and it's a string,
+		// check if it is a data URL
+		if (/^data:/.test(src)) {
+			// Preserve the data in this._data since canvas-node eats it.
+			// TODO: Fix canvas-node instead
+			image.src = this._data = src;
+		} else {
+			// Load it from disk:
+			// TODO: load images async, calling setImage once loaded as above.
+			image.src = fs.readFileSync(src);
+		}
+		this.setImage(image);
+/*#*/ } // options.node
 	},
 
 	// DOCS: document Raster#getElement
@@ -334,9 +341,14 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
 	toDataURL: function() {
 		// See if the linked image is base64 encoded already, if so reuse it,
 		// otherwise try using canvas.toDataURL()
+/*#*/ if (options.node) {
+		if (this._data)
+			return this._data;
+/*#*/ } else {
 		var src = this._image && this._image.src;
 		if (/^data:/.test(src))
 			return src;
+/*#*/ }
 		var canvas = this.getCanvas();
 		return canvas ? canvas.toDataURL() : null;
 	},
@@ -375,7 +387,7 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
 			bounds = new Rectangle(object);
 		} else if (object.x) {
 			// Create a rectangle of 1px size around the specified coordinates
-			bounds = Rectangle.create(object.x - 0.5, object.y - 0.5, 1, 1);
+			bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);
 		}
 		// Use a sample size of max 32 x 32 pixels, into which the path is
 		// scaled as a clipping path, and then the actual image is drawn in and
diff --git a/src/item/Shape.js b/src/item/Shape.js
index 3a11335f..100c1c66 100644
--- a/src/item/Shape.js
+++ b/src/item/Shape.js
@@ -17,12 +17,11 @@
  *
  * @extends Item
  */
-var Shape = this.Shape = Item.extend(/** @lends Shape# */{
-	_class: 'Shape',
+var Shape = Item.extend(/** @lends Shape# */{
 	_applyMatrix: false,
 
-	initialize: function(type, point, size) {
-		this.base(point);
+	initialize: function Shape(type, point, size) {
+		Item.call(this, point);
 		this._type = type;
 		this._size = size;
 	},
@@ -67,10 +66,10 @@ var Shape = this.Shape = Item.extend(/** @lends Shape# */{
 		}
 	},
 
-	_contains: function(point) {
+	_contains: function _contains(point) {
 		switch (this._type) {
 		case 'rect':
-			return this.base(point);
+			return _contains.base.call(this, point);
 		case 'circle':
 		case 'ellipse':
 			return point.divide(this._size).getLength() <= 0.5;
diff --git a/src/load.js b/src/load.js
index 97430850..73a5d453 100644
--- a/src/load.js
+++ b/src/load.js
@@ -14,17 +14,7 @@
 // 'preprocess' it on the fly in the browser, avoiding the step of having to
 // manually preprocess it after each change.
 
-// Define options for compile-time preprocessing.
-var options = {
-	parser: 'acorn',
-	version: 'dev',
-	browser: true,
-	stats: true,
-	svg: true,
-	fatline: true,
-	debug: false
-};
-
 // This folder is specified relatively to the lib folder from which prepro.js is
 // loaded, and which is referenced as the root.
+include('../src/options.js');
 include('../src/paper.js');
diff --git a/src/node/index.js b/src/node/index.js
index c9838a65..fe96aea3 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -16,24 +16,23 @@ var fs = require('fs'),
 	// Node Canvas library: https://github.com/learnboost/node-canvas
 	Canvas = require('canvas'),
 	jsdom = require('jsdom'),
-	domToHtml = require('jsdom/lib/jsdom/browser/domtohtml').domToHtml,
-	json = require('../../package.json');
+	domToHtml = require('jsdom/lib/jsdom/browser/domtohtml').domToHtml;
 
-var options = {
-	parser: 'acorn',
-	// Use 'dev' for on-the fly compilation of separate files ,but update after.
-	version: 'dev',
-	server: true,
-	svg: true,
-	fatline: false
-};
+// Load the options from load.js, but evaluate into local scope:
+eval(fs.readFileSync(path.resolve(__dirname, '../options.js'), 'utf8'));
+// Change node.js specific settings. Use 'dev' version for on-the fly
+// compilation of separate files, and set to correct value after.
+options.version = 'dev';
+options.browser = false;
+options.node = true;
+options.stats = false;
 
 // Create a document and a window using jsdom, e.g. for exportSVG()
 var doc = jsdom.jsdom("<html><body></body></html>"),
 	win = doc.createWindow();
 
-// Define XMLSerializer.
-// TODO: Put this into a simple node module, with dependency on jsdom
+// Define XMLSerializer and DOMParser shims, to emulate browser behavior.
+// TODO: Put this into a simple node module, with dependency on jsdom?
 function XMLSerializer() {
 }
 
@@ -41,7 +40,7 @@ XMLSerializer.prototype.serializeToString = function(node) {
 	var text = domToHtml(node);
 	// Fix a jsdom issue where linearGradient gets converted to lineargradient:
 	// https://github.com/tmpvar/jsdom/issues/620
-	return text.replace(/(linear|radial)(gradient)/g, function(all, type) {
+	return text.replace(/(linear|radial)gradient/g, function(all, type) {
 		return type + 'Gradient';
 	});
 };
@@ -89,26 +88,13 @@ var context = vm.createContext({
 // Load Paper.js library files:
 context.include('paper.js');
 
-// Since the context used for Paper.js compilation, and the context in which
-// Node.js scripts are executed do not share the definition of Object, we need
-// to redefine Base.isPlainObject() here.
-// So instead of checking for Object.prototype, we're checking
-// proto.constructor.name for 'Object'
-var Base = context.Base;
-Base.isPlainObject = function(obj) {
-	var proto = obj !== null && typeof obj === 'object'
-			&& Object.getPrototypeOf(obj);
-	return proto && (proto.constructor.name === 'Object'
-			|| proto === Base.prototype);
-};
-
 context.PaperScope.inject({
 	// Expose the Canvas, XMLSerializer & DOMParser to PaperScope:
 	Canvas: Canvas,
 	XMLSerializer: XMLSerializer,
 	DOMParser: DOMParser,
-	// Also fix version. Remove 2nd dot, so we can make a float out of it:
-	version: parseFloat(json.version.replace(/(.)(\d)$/, '$2'))
+	// Also set the correct version from package.json
+	version: require('../../package.json').version
 });
 
 require.extensions['.pjs'] = function(module, uri) {
diff --git a/src/options.js b/src/options.js
new file mode 100644
index 00000000..20d1e802
--- /dev/null
+++ b/src/options.js
@@ -0,0 +1,24 @@
+/*
+ * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
+ * http://paperjs.org/
+ *
+ * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
+ * http://lehni.org/ & http://jonathanpuckey.com/
+ *
+ * Distributed under the MIT license. See LICENSE file for details.
+ *
+ * All rights reserved.
+ */
+
+// Define default options for compile-time preprocessing. These are also used
+// for building, but some values are overridden (e.g. version, stats). 
+
+var options = {
+	parser: 'acorn',
+	version: 'dev',
+	browser: true,
+	stats: true,
+	svg: true,
+	fatline: false,
+	debug: false
+};
diff --git a/src/paper.js b/src/paper.js
index 964f64fc..abceb5a1 100644
--- a/src/paper.js
+++ b/src/paper.js
@@ -35,14 +35,14 @@ var paper = new function() {
 // Inline Bootstrap core (the Base class) inside the paper scope first:
 /*#*/ include('../lib/straps.js');
 
-/*#*/ if (options.version == 'dev') {
-/*#*/ include('constants.js');
-/*#*/ } // options.version == 'dev'
-
 /*#*/ if (options.stats) {
 /*#*/ include('../lib/stats.js');
 /*#*/ } // options.stats
 
+/*#*/ if (options.version == 'dev') {
+/*#*/ include('constants.js');
+/*#*/ } // options.version == 'dev'
+
 /*#*/ include('core/Base.js');
 /*#*/ include('core/Callback.js');
 /*#*/ include('core/PaperScope.js');
@@ -53,7 +53,7 @@ var paper = new function() {
 
 // Include Paper classes, which are later injected into PaperScope by setting
 // them on the 'this' object, e.g.:
-// var Point = this.Point = Base.extend(...);
+// var Point = Base.extend(...);
 
 /*#*/ include('basic/Point.js');
 /*#*/ include('basic/Size.js');
@@ -126,18 +126,7 @@ var paper = new function() {
 /*#*/ } // options.svg
 
 /*#*/ include('core/PaperScript.js');
-/*#*/ include('core/initialize.js');
 
-/*#*/ if (options.server) {
+/*#*/ include('export.js');
 return paper;
-/*#*/ } else if (options.version != 'dev') {
-// Finally inject the classes set on 'this' into the PaperScope class and create
-// the first PaperScope and return it, all in one statement.
-// The version for 'dev' of this happens in core/initialize.js, since it depends
-// on sequentiality of include() loading.
-// Mark this object as enumerable, so all the injected classes can be enumerated
-// again in PaperScope#install().
-this.enumerable = true;
-return new (PaperScope.inject(this));
-/*#*/ } // options.version != 'dev'
 };
diff --git a/src/path/CompoundPath.js b/src/path/CompoundPath.js
index 9cf5a976..c78b34fb 100644
--- a/src/path/CompoundPath.js
+++ b/src/path/CompoundPath.js
@@ -20,8 +20,7 @@
  *
  * @extends PathItem
  */
-var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
-	_class: 'CompoundPath',
+var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
 	_serializeFields: {
 		pathData: ''
 	},
@@ -49,8 +48,8 @@ var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath#
 	 * // Move the inner circle 5pt to the right:
 	 * compoundPath.children[1].position.x += 5;
 	 */
-	initialize: function(arg) {
-		this.base();
+	initialize: function CompoundPath(arg) {
+		PathItem.call(this);
 		// CompoundPath has children and supports named children.
 		this._children = [];
 		this._namedChildren = {};
@@ -58,18 +57,20 @@ var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath#
 			this.addChildren(Array.isArray(arg) ? arg : arguments);
 	},
 
-	insertChild: function(index, item, _preserve) {
-		// Only allow the insertion of paths
-		if (item._type !== 'path')
-			return null;
-		item = this.base(index, item);
+	insertChildren: function insertChildren(index, items, _preserve) {
+		// Pass on 'path' for _type, to make sure that only paths are added as
+		// children.
+		items = insertChildren.base.call(this, index, items, _preserve, 'path');
 		// All children except for the bottom one (first one in list) are set
 		// to anti-clockwise orientation, so that they appear as holes, but
 		// only if their orientation was not already specified before
 		// (= _clockwise is defined).
-		if (!_preserve && item && item._clockwise === undefined)
-			item.setClockwise(item._index == 0);
-		return item;
+		for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
+			var item = items[i];
+			if (item._clockwise === undefined)
+				item.setClockwise(item._index === 0);
+		}
+		return items;
 	},
 
 	/**
@@ -223,8 +224,9 @@ var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath#
 		return (children.length & 1) == 1 && children;
 	},
 
-	_hitTest: function(point, options) {
-		var res = this.base(point, Base.merge(options, { fill: false }));
+	_hitTest: function _hitTest(point, options) {
+		var res = _hitTest.base.call(this, point,
+				Base.merge(options, { fill: false }));
 		if (!res && options.fill && this._style.getFillColor()) {
 			res = this._contains(point);
 			res = res ? new HitResult('fill', res[0]) : null;
diff --git a/src/path/Curve.js b/src/path/Curve.js
index 0ff336be..42101d65 100644
--- a/src/path/Curve.js
+++ b/src/path/Curve.js
@@ -24,7 +24,7 @@
  * convenient ways to work with parts of the path, finding lengths, positions or
  * tangents at given offsets.
  */
-var Curve = this.Curve = Base.extend(/** @lends Curve# */{
+var Curve = Base.extend(/** @lends Curve# */{
 	/**
 	 * Creates a new curve object.
 	 *
@@ -55,7 +55,7 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{
 	 * @param {Number} x2
 	 * @param {Number} y2
 	 */
-	initialize: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
+	initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
 		var count = arguments.length;
 		if (count === 0) {
 			this._segment1 = new Segment();
@@ -243,7 +243,7 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{
 		var coords = this.getValues(),
 			points = [];
 		for (var i = 0; i < 8; i += 2)
-			points.push(Point.create(coords[i], coords[i + 1]));
+			points.push(new Point(coords[i], coords[i + 1]));
 		return points;
 	},
 
@@ -408,9 +408,9 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{
 
 			// Create the new segment, convert absolute -> relative:
 			var x = left[6], y = left[7],
-				segment = new Segment(Point.create(x, y),
-						!isLinear && Point.create(left[4] - x, left[5] - y),
-						!isLinear && Point.create(right[2] - x, right[3] - y));
+				segment = new Segment(new Point(x, y),
+						!isLinear && new Point(left[4] - x, left[5] - y),
+						!isLinear && new Point(right[2] - x, right[3] - y));
 
 			// Insert it in the segments list, if needed:
 			if (this._path) {
@@ -662,7 +662,7 @@ statics: {
 		for (var i = 0; i < 2; i++)
 			Curve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],
 					i, 0, min, max, roots);
-		return Rectangle.create(min[0], min[1], max[0] - min[0], max[1] - min[1]);
+		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
 	},
 
 	/**
@@ -697,8 +697,8 @@ statics: {
 		// Only add strokeWidth to bounds for points which lie  within 0 < t < 1
 		// The corner cases for cap and join are handled in getStrokeBounds()
 		add(v3, 0);
-		for (var j = 0; j < count; j++) {
-			var t = roots[j],
+		for (var i = 0; i < count; i++) {
+			var t = roots[i],
 				u = 1 - t;
 			// Test for good roots and only add to bounds if good.
 			if (tMin < t && t < tMax)
@@ -1023,7 +1023,7 @@ new function() { // Scope for methods that require numerical integration
 					a, b, 16, /*#=*/ Numerical.TOLERANCE);
 		}
 	};
-}, new function() { // Scope for Curve intersection
+}, new function() { // Scope for intersection using bezier fat-line clipping
 	function addLocation(locations, curve1, parameter, point, curve2) {
 		// Avoid duplicates when hitting segments (closed paths too)
 		var first = locations[0],
@@ -1033,7 +1033,7 @@ new function() { // Scope for methods that require numerical integration
 			locations.push(new CurveLocation(curve1, parameter, point, curve2));
 	}
 
-	function getCurveIntersections(v1, v2, curve1, curve2, locations,
+	function addCurveIntersections(v1, v2, curve1, curve2, locations,
 			range1, range2, recursion) {
 /*#*/ if (options.fatline) {
 		// NOTE: range1 and range1 are only used for recusion
@@ -1097,17 +1097,17 @@ new function() { // Scope for methods that require numerical integration
 				if (range1[1] - range1[0] > range2[1] - range2[0]) {
 					// subdivide v1 and recurse
 					var t = (range1[0] + range1[1]) / 2;
-					getCurveIntersections(v1, v2, curve1, curve2, locations,
+					addCurveIntersections(v1, v2, curve1, curve2, locations,
 							[ range1[0], t ], range2, recursion);
-					getCurveIntersections(v1, v2, curve1, curve2, locations,
+					addCurveIntersections(v1, v2, curve1, curve2, locations,
 							[ t, range1[1] ], range2, recursion);
 					break;
 				} else {
 					// subdivide v2 and recurse
 					var t = (range2[0] + range2[1]) / 2;
-					getCurveIntersections(v1, v2, curve1, curve2, locations,
+					addCurveIntersections(v1, v2, curve1, curve2, locations,
 							range1, [ range2[0], t ], recursion);
-					getCurveIntersections(v1, v2, curve1, curve2, locations,
+					addCurveIntersections(v1, v2, curve1, curve2, locations,
 							range1, [ t, range2[1] ], recursion);
 					break;
 				}
@@ -1123,12 +1123,16 @@ new function() { // Scope for methods that require numerical integration
 			// Check if one of the parameter range has converged completely to a
 			// point. Now things could get only worse if we iterate more for the
 			// other curve to converge if it hasn't yet happened so.
-			var converged1 = Math.abs(range1[1] - range1[0]) < /*#=*/ Numerical.TOLERANCE,
-				converged2 = Math.abs(range2[1] - range2[0]) < /*#=*/ Numerical.TOLERANCE;
-			if (converged1 || converged2) {
-				addLocation(locations, curve1, null, converged1
-						? curve1.getPointAt(range1[0], true)
-						: curve2.getPointAt(range2[0], true), curve2);
+			if (Math.abs(range1[1] - range1[0]) < /*#=*/ Numerical.TOLERANCE) {
+				var t = (range1[0] + range1[1]) / 2;
+				addLocation(locations, curve1, t,
+						Curve.evaluate(v1, t, true, 0), curve2);
+				break;
+			}
+			if (Math.abs(range2[1] - range2[0]) < /*#=*/ Numerical.TOLERANCE) {
+				var t = (range2[0] + range2[1]) / 2;
+				addLocation(locations, curve2, t,
+						Curve.evaluate(v2, t, true, 0), curve1);
 				break;
 			}
 			// see if either or both of the curves are flat enough to be treated
@@ -1137,10 +1141,10 @@ new function() { // Scope for methods that require numerical integration
 				flat2 = Curve.isFlatEnough(part2, /*#=*/ Numerical.TOLERANCE);
 			if (flat1 || flat2) {
 				(flat1 && flat2
-						? getLineLineIntersection
+						? addLineIntersection
 						// Use curve line intersection method while specifying
 						// which curve to be treated as line
-						: getCurveLineIntersections)(part1, part2,
+						: addCurveLineIntersections)(part1, part2,
 								curve1, curve2, locations, flat1);
 				break;
 			}
@@ -1158,15 +1162,7 @@ new function() { // Scope for methods that require numerical integration
 				&& (Curve.isLinear(v2)
 					|| Curve.isFlatEnough(v2, /*#=*/ Numerical.TOLERANCE))) {
 				// See if the parametric equations of the lines interesct.
-				// var point = new Line(v1[0], v1[1], v1[6], v1[7], false)
-				//	  .intersect(new Line(v2[0], v2[1], v2[6], v2[7], false));
-				// Use static version without creation of Line objects, but it
-				// doesn't seem to yield measurable speed improvements!
-				var point = Line.intersect(
-							v1[0], v1[1], v1[6], v1[7],
-							v2[0], v2[1], v2[6], v2[7], false);
-				if (point)
-					addLocation(locations, curve1, null, point, curve2);
+				addLineIntersection(v1, v2, curve1, curve2, locations);
 			} else {
 				// Subdivide both curves, and see if they intersect.
 				// If one of the curves is flat already, no further subdivion
@@ -1200,6 +1196,7 @@ new function() { // Scope for methods that require numerical integration
 			p2x = v1[4], p2y = v1[5], p3x = v1[6], p3y = v1[7],
 			q0x = v2[0], q0y = v2[1], q1x = v2[2], q1y = v2[3],
 			q2x = v2[4], q2y = v2[5], q3x = v2[6], q3y = v2[7],
+			getSignedDistance = Line.getSignedDistance,
 			// Calculate the fat-line L for P is the baseline l and two
 			// offsets which completely encloses the curve P.
 			d1 = getSignedDistance(p0x, p0y, p3x, p3y, p1x, p1y) || 0,
@@ -1213,20 +1210,19 @@ new function() { // Scope for methods that require numerical integration
 			dq0 = getSignedDistance(p0x, p0y, p3x, p3y, q0x, q0y),
 			dq1 = getSignedDistance(p0x, p0y, p3x, p3y, q1x, q1y),
 			dq2 = getSignedDistance(p0x, p0y, p3x, p3y, q2x, q2y),
-			dq3 = getSignedDistance(p0x, p0y, p3x, p3y, q3x, q3y),
-			// Find the minimum and maximum distances from l, this is useful for
-			// checking whether the curves intersect with each other or not.
-			mindist = Math.min(dq0, dq1, dq2, dq3),
-			maxdist = Math.max(dq0, dq1, dq2, dq3);
+			dq3 = getSignedDistance(p0x, p0y, p3x, p3y, q3x, q3y);
+		// Find the minimum and maximum distances from l, this is useful for
+		// checking whether the curves intersect with each other or not.
 		// If the fatlines don't overlap, we have no intersections!
-		if (dmin > maxdist || dmax < mindist)
+		if (dmin > Math.max(dq0, dq1, dq2, dq3)
+				|| dmax < Math.min(dq0, dq1, dq2, dq3))
 			return 0;
-		var Dt = getConvexHull(dq0, dq1, dq2, dq3),
-			tmp;
+		var hull = getConvexHull(dq0, dq1, dq2, dq3),
+			swap;
 		if (dq3 < dq0) {
-			tmp = dmin;
+			swap = dmin;
 			dmin = dmax;
-			dmax = tmp;
+			dmax = swap;
 		}
 		// Calculate the convex hull for non-parametric bezier curve D(ti, di(t))
 		// Now we clip the convex hulls for D(ti, di(t)) with dmin and dmax
@@ -1235,31 +1231,29 @@ new function() { // Scope for methods that require numerical integration
 		var tmaxdmin = -Infinity,
 			tmin = Infinity,
 			tmax = -Infinity;
-		for (var i = 0, l = Dt.length; i < l; i++) {
-			var Dtl = Dt[i],
-				dtlx1 = Dtl[0],
-				dtly1 = Dtl[1],
-				dtlx2 = Dtl[2],
-				dtly2 = Dtl[3];
-			if (dtly2 < dtly1) {
-				tmp = dtly2;
-				dtly2 = dtly1;
-				dtly1 = tmp;
-				tmp = dtlx2;
-				dtlx2 = dtlx1;
-				dtlx1 = tmp;
+		for (var i = 0, l = hull.length; i < l; i++) {
+			var p1 = hull[i],
+				p2 = hull[(i + 1) % l];
+			if (p2[1] < p1[1]) {
+				swap = p2;
+				p2 = p1;
+				p1 = swap;
 			}
-			// We know that (dtlx2 - dtlx1) is never 0
-			var inv = (dtly2 - dtly1) / (dtlx2 - dtlx1);
-			if (dmin >= dtly1 && dmin <= dtly2) {
-				var ixdx = dtlx1 + (dmin - dtly1) / inv;
+			var	x1 = p1[0],
+				y1 = p1[1],
+				x2 = p2[0],
+				y2 = p2[1];
+			// We know that (x2 - x1) is never 0
+			var inv = (y2 - y1) / (x2 - x1);
+			if (dmin >= y1 && dmin <= y2) {
+				var ixdx = x1 + (dmin - y1) / inv;
 				if (ixdx < tmin)
 					tmin = ixdx;
 				if (ixdx > tmaxdmin)
 					tmaxdmin = ixdx;
 			}
-			if (dmax >= dtly1 && dmax <= dtly2) {
-				var ixdx = dtlx1 + (dmax - dtly1) / inv;
+			if (dmax >= y1 && dmax <= y2) {
+				var ixdx = x1 + (dmax - y1) / inv;
 				if (ixdx > tmax)
 					tmax = ixdx;
 				if (ixdx < tmin)
@@ -1269,11 +1263,11 @@ new function() { // Scope for methods that require numerical integration
 		// Return the parameter values for v2 for which we can be sure that the
 		// intersection with v1 lies within.
 		if (tmin !== Infinity && tmax !== -Infinity) {
-			var mindmin = Math.min(dmin, dmax),
-				mindmax = Math.max(dmin, dmax);
-			if (dq3 > mindmin && dq3 < mindmax)
+			var min = Math.min(dmin, dmax),
+				max = Math.max(dmin, dmax);
+			if (dq3 > min && dq3 < max)
 				tmax = 1;
-			if (dq0 > mindmin && dq0 < mindmax)
+			if (dq0 > min && dq0 < max)
 				tmin = 0;
 			if (tmaxdmin > tmax)
 				tmax = 1;
@@ -1304,79 +1298,48 @@ new function() { // Scope for methods that require numerical integration
 	 * Calculating convex-hull is much easier than a set of arbitrary points.
 	 */
 	function getConvexHull(dq0, dq1, dq2, dq3) {
-		var distq1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1),
-			distq2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2);
-		// Check if [1/3, dq1] and [2/3, dq2] are on the same side of line
-		// [0,dq0, 1,dq3]
-		if (distq1 * distq2 < 0) {
-			// dq1 and dq2 lie on different sides on [0, q0, 1, q3]. The hull is
-			// a quadrilateral and line [0, q0, 1, q3] is NOT part of the hull
-			// so we are pretty much done here.
-			return [
-				[ 0, dq0, 1 / 3, dq1 ],
-				[ 1 / 3, dq1, 1, dq3 ],
-				[ 2 / 3, dq2, 0, dq0 ],
-				[ 1, dq3, 2 / 3, dq2 ]
-			];
+		var p0 = [ 0, dq0 ],
+			p1 = [ 1 / 3, dq1 ],
+			p2 = [ 2 / 3, dq2 ],
+			p3 = [ 1, dq3 ],
+			// Find signed distance of p1 and p2 from line [ p0, p3 ]
+			getSignedDistance = Line.getSignedDistance,
+			dist1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1),
+			dist2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2);
+		// Check if p1 and p2 are on the same side of the line [ p0, p3 ]
+		if (dist1 * dist2 < 0) {
+			// p1 and p2 lie on different sides of [ p0, p3 ]. The hull is a
+			// quadrilateral and line [ p0, p3 ] is NOT part of the hull so we
+			// are pretty much done here.
+			return [ p0, p1, p3, p2 ];
 		}
-		// dq1 and dq2 lie on the same sides on [0, q0, 1, q3]. The hull can be
-		// a triangle or a quadrilateral and line [0, q0, 1, q3] is part of the
+		// p1 and p2 lie on the same sides of [ p0, p3 ]. The hull can be
+		// a triangle or a quadrilateral and line [ p0, p3 ] is part of the
 		// hull. Check if the hull is a triangle or a quadrilateral.
-		var dqMaxX, dqMaxY, vqa1a2X, vqa1a2Y, vqa1MaxX, vqa1MaxY, vqa1MinX, vqa1MinY;
-		if (Math.abs(distq1) > Math.abs(distq2)) {
-			dqMaxX = 1 / 3;
-			dqMaxY = dq1;
+		var pmax, cross;
+		if (Math.abs(dist1) > Math.abs(dist2)) {
+			pmax = p1;
 			// apex is dq3 and the other apex point is dq0 vector
 			// dqapex->dqapex2 or base vector which is already part of the hull.
-			vqa1a2X = 1;
-			vqa1a2Y = dq3 - dq0;
-			// vector dqapex->dqMax
-			vqa1MaxX = 2 / 3;
-			vqa1MaxY = dq3 - dq1;
-			// vector dqapex->dqmin
-			vqa1MinX = 1 / 3;
-			vqa1MinY = dq3 - dq2;
+			// cross = (vqa1a2X * vqa1MinY - vqa1a2Y * vqa1MinX)
+			//		* (vqa1MaxX * vqa1MinY - vqa1MaxY * vqa1MinX)
+			cross = (dq3 - dq2 - (dq3 - dq0) / 3)
+					* (2 * (dq3 - dq2) - dq3 + dq1) / 3;
 		} else {
-			dqMaxX = 2 / 3;
-			dqMaxY = dq2;
+			pmax = p2;
 			// apex is dq0 in this case, and the other apex point is dq3 vector
 			// dqapex->dqapex2 or base vector which is already part of the hull.
-			vqa1a2X = -1;
-			vqa1a2Y = dq0 - dq3;
-			// vector dqapex->dqMax
-			vqa1MaxX = -2 / 3;
-			vqa1MaxY = dq0 - dq2;
-			// vector dqapex->dqmin
-			vqa1MinX = -1 / 3;
-			vqa1MinY = dq0 - dq1;
+			cross = (dq1 - dq0 + (dq0 - dq3) / 3)
+					* (-2 * (dq0 - dq1) + dq0 - dq2) / 3;
 		}
-		// Compare cross products of these vectors to determine, if
-		// point is in triangles [ dq3, dqMax, dq0 ] or [ dq0, dqMax, dq3 ]
-		var a1a2_a1Min = vqa1a2X * vqa1MinY - vqa1a2Y * vqa1MinX,
-			a1Max_a1Min = vqa1MaxX * vqa1MinY - vqa1MaxY * vqa1MinX;
-		return a1a2_a1Min * a1Max_a1Min < 0
-				// Point [2/3, dq2] is inside the triangle, hull is a triangle.
-				? [
-					[ 0, dq0, dqMaxX, dqMaxY ],
-					[ dqMaxX, dqMaxY, 1, dq3 ],
-					[ 1, dq3, 0, dq0 ]
-				]
+		// Compare cross products of these vectors to determine if the point is
+		// in the triangle [ p3, pmax, p0 ], or if it is a quadrilateral.
+		return cross < 0
+				// p2 is inside the triangle, hull is a triangle.
+				? [ p0, pmax, p3 ]
 				// Convexhull is a quadrilateral and we need all lines in the
-				// correct order where line [0, q0, 1, q3] is part of the hull.
-				: [
-					[ 0, dq0, 1 / 3, dq1 ],
-					[ 1 / 3, dq1, 2 / 3, dq2 ],
-					[ 2 / 3, dq2, 1, dq3 ],
-					[ 1, dq3, 0, dq0 ]
-				];
-	}
-
-	// This is basically an "unrolled" version of #Line.getDistance() with sign
-	// May be a static method could be better!
-	function getSignedDistance(a1x, a1y, a2x, a2y, bx, by) {
-		var m = (a2y - a1y) / (a2x - a1x),
-			b = a1y - (m * a1x);
-		return (by - (m * bx) - b) / Math.sqrt(m * m + 1);
+				// correct order where line [ p1, p3 ] is part of the hull.
+				: [ p0, p1, p2, p3 ];
 	}
 /*#*/ } // options.fatline
 
@@ -1386,7 +1349,7 @@ new function() { // Scope for methods that require numerical integration
 	 * line is on the X axis, and solve the implicit equations for the X axis
 	 * and the curve.
 	 */
-	function getCurveLineIntersections(v1, v2, curve1, curve2, locations, flip) {
+	function addCurveLineIntersections(v1, v2, curve1, curve2, locations, flip) {
 		if (flip === undefined)
 			flip = Curve.isLinear(v1);
 		var vc = flip ? v2 : v1,
@@ -1432,17 +1395,17 @@ new function() { // Scope for methods that require numerical integration
 		}
 	}
 
-	function getLineLineIntersection(v1, v2, curve1, curve2, locations) {
+	function addLineIntersection(v1, v2, curve1, curve2, locations) {
 		var point = Line.intersect(
 				v1[0], v1[1], v1[6], v1[7],
-				v2[0], v2[1], v2[6], v2[7], false);
+				v2[0], v2[1], v2[6], v2[7]);
 		// Passing null for parameter leads to lazy determination of parameter
 		// values in CurveLocation#getParameter() only once they are requested.
 		if (point)
 			addLocation(locations, curve1, null, point, curve2);
 	}
 
-	return { statics: {
+	return { statics: /** @lends Curve */{
 		// We need to provide the original left curve reference to the
 		// #getIntersections() calls as it is required to create the resulting
 		// CurveLocation objects.
@@ -1452,10 +1415,10 @@ new function() { // Scope for methods that require numerical integration
 			// Determine the correct intersection method based on values of
 			// linear1 & 2:
 			(linear1 && linear2
-				? getLineLineIntersection
+				? addLineIntersection
 				: linear1 || linear2
-					? getCurveLineIntersections
-					: getCurveIntersections)(v1, v2, curve1, curve2, locations);
+					? addCurveLineIntersections
+					: addCurveIntersections)(v1, v2, curve1, curve2, locations);
 			return locations;
 		}
 	}};
diff --git a/src/path/CurveLocation.js b/src/path/CurveLocation.js
index 197ae76c..0846a563 100644
--- a/src/path/CurveLocation.js
+++ b/src/path/CurveLocation.js
@@ -26,7 +26,7 @@
  * {@link PathItem#getIntersections(path)},
  * etc.
  */
-var CurveLocation = this.CurveLocation = Base.extend(/** @lends CurveLocation# */{
+var CurveLocation = Base.extend(/** @lends CurveLocation# */{
 	// DOCS: CurveLocation class description: add these back when the  mentioned
 	// functioned have been added: {@link Path#split(location)}
 	/**
@@ -36,7 +36,8 @@ var CurveLocation = this.CurveLocation = Base.extend(/** @lends CurveLocation# *
 	 * @param {Number} parameter
 	 * @param {Point} point
 	 */
-	initialize: function(curve, parameter, point, _otherCurve, _distance) {
+	initialize: function CurveLocation(curve, parameter, point, _otherCurve,
+			_distance) {
 		// Define this CurveLocation's unique id.
 		this._id = CurveLocation._id = (CurveLocation._id || 0) + 1;
 		this._curve = curve;
diff --git a/src/path/Path.Constructors.js b/src/path/Path.Constructors.js
index 16632ab0..a4c00d6f 100644
--- a/src/path/Path.Constructors.js
+++ b/src/path/Path.Constructors.js
@@ -274,7 +274,7 @@ Path.inject({ statics: new function() {
 			var center = Point.readNamed(arguments, 'center'),
 				radius = Base.readNamed(arguments, 'radius');
 			return createEllipse(new Rectangle(center.subtract(radius),
-					Size.create(radius * 2, radius * 2)))
+					new Size(radius * 2, radius * 2)))
 					.set(Base.getNamed(arguments));
 		},
 
diff --git a/src/path/Path.js b/src/path/Path.js
index de5afa2c..59de01c8 100644
--- a/src/path/Path.js
+++ b/src/path/Path.js
@@ -18,8 +18,7 @@
  * @extends PathItem
  */
 // DOCS: Explain that path matrix is always applied with each transformation.
-var Path = this.Path = PathItem.extend(/** @lends Path# */{
-	_class: 'Path',
+var Path = PathItem.extend(/** @lends Path# */{
 	_serializeFields: {
 		segments: [],
 		closed: false
@@ -67,10 +66,10 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
 	 * 	selected: true
 	 * });
 	 */
-	initialize: function(arg) {
+	initialize: function Path(arg) {
 		this._closed = false;
 		this._segments = [];
-		this.base();
+		Item.call(this);
 		// arg can either be an object literal describing properties to be set
 		// on the path, a list of segments to be set, or the first of multiple
 		// arguments describing separate segments.
@@ -788,12 +787,12 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
 		this.setSelected(selected);
 	},
 
-	setSelected: function(selected) {
+	setSelected: function setSelected(selected) {
 		// Deselect all segments when path is marked as not selected
 		if (!selected)
 			this._selectSegments(false);
 		// No need to pass true for noChildren since Path has none anyway.
-		this.base(selected);
+		setSelected.base.call(this, selected);
 	},
 
 	_selectSegments: function(selected) {
@@ -1982,13 +1981,13 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
 					segment.setHandleIn(handleIn.subtract(segment._point));
 				if (i < n) {
 					segment.setHandleOut(
-							Point.create(x[i], y[i]).subtract(segment._point));
+							new Point(x[i], y[i]).subtract(segment._point));
 					if (i < n - 1)
-						handleIn = Point.create(
+						handleIn = new Point(
 								2 * knots[i + 1]._x - x[i + 1],
 								2 * knots[i + 1]._y - y[i + 1]);
 					else
-						handleIn = Point.create(
+						handleIn = new Point(
 								(knots[n]._x + x[n - 1]) / 2,
 								(knots[n]._y + y[n - 1]) / 2);
 				}
@@ -2104,11 +2103,11 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
 			// Construct the two perpendicular middle lines to (from, through)
 			// and (through, to), and intersect them to get the center
 			var l1 = new Line(from.add(through).divide(2),
-					through.subtract(from).rotate(90)),
+						through.subtract(from).rotate(90), true),
 				l2 = new Line(through.add(to).divide(2),
-					to.subtract(through).rotate(90)),
-				center = l1.intersect(l2),
-				line = new Line(from, to, true),
+						to.subtract(through).rotate(90), true),
+				center = l1.intersect(l2, true),
+				line = new Line(from, to),
 				throughSide = line.getSide(through);
 			if (!center) {
 				// If the two lines are colinear, there cannot be an arc as the
@@ -2179,7 +2178,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
 			throughVector = Point.read(throughVector);
 			toVector = Point.read(toVector);
 			var current = getCurrentSegment(this)._point;
-			this.arcBy(current.add(throughVector), current.add(toVector));
+			this.arcTo(current.add(throughVector), current.add(toVector));
 		},
 
 		closePath: function() {
@@ -2283,7 +2282,7 @@ statics: {
 			processSegment(segments[i]);
 		if (closed)
 			processSegment(first);
-		return Rectangle.create(min[0], min[1], max[0] - min[0], max[1] - min[1]);
+		return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
 	},
 
 	/**
@@ -2305,8 +2304,8 @@ statics: {
 			// Get rotated hor and ver vectors, and determine rotation angle
 			// and elipse values from them:
 			var mx = matrix.shiftless(),
-				hor = mx.transform(Point.create(radius, 0)),
-				ver = mx.transform(Point.create(0, radius)),
+				hor = mx.transform(new Point(radius, 0)),
+				ver = mx.transform(new Point(0, radius)),
 				phi = hor.getAngleInRadians(),
 				a = hor.getLength(),
 				b = ver.getLength();
@@ -2389,10 +2388,10 @@ statics: {
 					normal2 = curve2.getNormalAt(0, true).normalize(miterRadius),
 					// Intersect the two lines
 					line1 = new Line(point.add(normal1),
-							Point.create(-normal1.y, normal1.x)),
+							new Point(-normal1.y, normal1.x), true),
 					line2 = new Line(point.add(normal2),
-							Point.create(-normal2.y, normal2.x)),
-					corner = line1.intersect(line2);
+							new Point(-normal2.y, normal2.x), true),
+					corner = line1.intersect(line2, true);
 				// Now measure the distance from the segment to the
 				// intersection, which his half of the miter distance
 				if (!corner || point.getDistance(corner) > miterLimit) {
@@ -2466,7 +2465,7 @@ statics: {
 				if (yx > y2) y2 = yx;
 			}
 		}
-		return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
+		return new Rectangle(x1, y1, x2 - x1, y2 - y1);
 	},
 
 	/**
diff --git a/src/path/PathItem.Boolean.js b/src/path/PathItem.Boolean.js
index f77961b1..fbbafd6c 100644
--- a/src/path/PathItem.Boolean.js
+++ b/src/path/PathItem.Boolean.js
@@ -158,7 +158,7 @@ PathItem.inject(new function() {
 			if (segment.getPrevious()._invalid)
 				segment.setHandleIn(intersection
 						? intersection._handleIn
-						: Point.create(0, 0));
+						: new Point(0, 0));
 			do {
 				segment._visited = true;
 				if (segment._invalid && segment._intersection) {
diff --git a/src/path/PathItem.js b/src/path/PathItem.js
index c2d51f30..0abd3a8e 100644
--- a/src/path/PathItem.js
+++ b/src/path/PathItem.js
@@ -19,7 +19,11 @@
  *
  * @extends Item
  */
-var PathItem = this.PathItem = Item.extend(/** @lends PathItem# */{
+var PathItem = Item.extend(/** @lends PathItem# */{
+	initialize: function PathItem() {
+		Item.apply(this, arguments);
+	},
+
 	/**
 	 * Returns all intersections between two {@link PathItem} items as an array
 	 * of {@link CurveLocation} objects. {@link CompoundPath} items are also
diff --git a/src/path/Segment.js b/src/path/Segment.js
index b8e036eb..9ed40a7c 100644
--- a/src/path/Segment.js
+++ b/src/path/Segment.js
@@ -22,9 +22,7 @@
  * {@link Segment#handleOut}), describing the tangents of the two {@link Curve}
  * objects that are connected by this segment.
  */
-var Segment = this.Segment = Base.extend(/** @lends Segment# */{
-	_class: 'Segment',
-
+var Segment = Base.extend(/** @lends Segment# */{
 	/**
 	 * Creates a new Segment object.
 	 *
@@ -110,7 +108,7 @@ var Segment = this.Segment = Base.extend(/** @lends Segment# */{
 	 * path.strokeColor = 'black';
 	 * @ignore
 	 */
-	initialize: function(arg0, arg1, arg2, arg3, arg4, arg5) {
+	initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
 		var count = arguments.length,
 			createPoint = SegmentPoint.create,
 			point, handleIn, handleOut;
diff --git a/src/project/Project.js b/src/project/Project.js
index 5f71d2fa..d7be6c20 100644
--- a/src/project/Project.js
+++ b/src/project/Project.js
@@ -30,7 +30,7 @@
  * An array of all open projects is accessible through the
  * {@link PaperScope#projects} variable.
  */
-var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
+var Project = PaperScopeItem.extend(/** @lends Project# */{
 	_list: 'projects',
 	_reference: 'project',
 
@@ -44,10 +44,10 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
 	 * @param {View|HTMLCanvasElement} view Either a view object or an HTML
 	 * Canvas element that should be wrapped in a newly created view.
 	 */
-	initialize: function(view) {
+	initialize: function Project(view) {
 		// Activate straight away by passing true to base(), so paper.project is
 		// set, as required by Layer and DoumentView constructors.
-		this.base(true);
+		PaperScopeItem.call(this, true);
 		this.layers = [];
 		this.symbols = [];
 		this._currentStyle = new Style();
@@ -69,12 +69,8 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
 		// into the active project automatically. We might want to add proper
 		// project serialization later, but deserialization of a layers array
 		// will always work.
-		return Base.serialize(this.layers, options, false, dictionary);
-	},
-
-	_needsRedraw: function() {
-		if (this.view)
-			this.view._redrawNeeded = true;
+		// Pass true for compact, so 'Project' does not get added as the class
+		return Base.serialize(this.layers, options, true, dictionary);
 	},
 
 	/**
@@ -97,8 +93,8 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
 	 * Removes this project from the {@link PaperScope#projects} list, and also
 	 * removes its view, if one was defined.
 	 */
-	remove: function() {
-		if (!this.base())
+	remove: function remove() {
+		if (!remove.base.call(this))
 			return false;
 		if (this.view)
 			this.view.remove();
@@ -271,6 +267,7 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
 	// DOCS: Figure out a way to group these together with importSVG / exportSVG
 
 	importJSON: function(json) {
+		this.activate();
 		return Base.importJSON(json);
 	},
 
diff --git a/src/project/Symbol.js b/src/project/Symbol.js
index 30eda0ba..02fa7aa7 100644
--- a/src/project/Symbol.js
+++ b/src/project/Symbol.js
@@ -19,9 +19,7 @@
  * internal properties such as segment lists and gradient positions don't need
  * to be updated with every transformation.
  */
-var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
-	_class: 'Symbol',
-
+var Symbol = Base.extend(/** @lends Symbol# */{
 	/**
 	 * Creates a Symbol item.
 	 *
@@ -59,7 +57,7 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
 	 *     instance.scale(0.25 + Math.random() * 0.75);
 	 * }
 	 */
-	initialize: function(item, dontCenter) {
+	initialize: function Symbol(item, dontCenter) {
 		// Define this Symbols's unique id.
 		this._id = Symbol._id = (Symbol._id || 0) + 1;
 		this.project = paper.project;
@@ -72,7 +70,7 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
 
 	_serialize: function(options, dictionary) {
 		return dictionary.add(this, function() {
-			return Base.serialize([this._class, this._definition],
+			return Base.serialize([this.constructor.name, this._definition],
 					options, false, dictionary);
 		});
 	},
diff --git a/src/style/Color.js b/src/style/Color.js
index 52e402e8..13ed0a8c 100644
--- a/src/style/Color.js
+++ b/src/style/Color.js
@@ -40,7 +40,7 @@
  * // converted to a Color.
  * circle.fillColor = '#ff0000';
  */
-var Color = this.Color = Base.extend(new function() {
+var Color = Base.extend(new function() {
 
 	var types = {
 		gray: ['gray'],
@@ -275,7 +275,6 @@ var Color = this.Color = Base.extend(new function() {
 			};
 		}, this);
 	}, /** @lends Color# */{
-		_class: 'Color',
 		// Tell Base.read that the Point constructor supports reading with index
 		_readIndex: true,
 
@@ -436,7 +435,7 @@ var Color = this.Color = Base.extend(new function() {
 		 * // 100% and a lightness of 50%:
 		 * circle.fillColor = { hue: 90, saturation: 1, lightness: 0.5 };
 		 */
-		initialize: function(arg) {
+		initialize: function Color(arg) {
 			// We are storing color internally as an array of components
 			var slice = Array.prototype.slice,
 				args = arguments,
@@ -503,7 +502,7 @@ var Color = this.Color = Base.extend(new function() {
 							: nameToRGB(arg);
 					type = 'rgb';
 				} else if (argType === 'object') {
-					if (arg._class === 'Color') {
+					if (arg.constructor === Color) {
 						type = arg._type;
 						components = arg._components.slice();
 						alpha = arg._alpha;
@@ -516,7 +515,7 @@ var Color = this.Color = Base.extend(new function() {
 									components[i] = point.clone();
 							}
 						}
-					} else if (arg._class === 'Gradient') {
+					} else if (arg.constructor === Gradient) {
 						type = 'gradient';
 						values = args;
 					} else {
diff --git a/src/style/Gradient.js b/src/style/Gradient.js
index e135f28f..468b1676 100644
--- a/src/style/Gradient.js
+++ b/src/style/Gradient.js
@@ -59,11 +59,9 @@
  * 	destination: path.bounds.rightCenter
  * };
  */
-var Gradient = this.Gradient = Base.extend(/** @lends Gradient# */{
-	_class: 'Gradient',
-
+var Gradient = Base.extend(/** @lends Gradient# */{
 	// DOCS: Document #initialize()
-	initialize: function(stops, radial) {
+	initialize: function Gradient(stops, radial) {
 		// Define this Gradient's unique id.
 		this._id = Gradient._id = (Gradient._id || 0) + 1;
 		if (stops && this._set(stops))
diff --git a/src/style/GradientStop.js b/src/style/GradientStop.js
index d3602a0d..d9da5437 100644
--- a/src/style/GradientStop.js
+++ b/src/style/GradientStop.js
@@ -16,7 +16,7 @@
  *
  * @class The GradientStop object.
  */
-var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
+var GradientStop = Base.extend(/** @lends GradientStop# */{
 	/**
 	 * Creates a GradientStop object.
 	 *
@@ -24,7 +24,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
 	 * @param {Number} [rampPoint=0] the position of the stop on the gradient
 	 *                               ramp as a value between 0 and 1.
 	 */
-	initialize: function(arg0, arg1) {
+	initialize: function GradientStop(arg0, arg1) {
 		if (arg0) {
 			var color, rampPoint;
 			if (arg1 === undefined && Array.isArray(arg0)) {
diff --git a/src/style/Style.js b/src/style/Style.js
index b965dbb8..5267ba49 100644
--- a/src/style/Style.js
+++ b/src/style/Style.js
@@ -65,7 +65,7 @@
  * };
  * 
  */
-var Style = this.Style = Base.extend(new function() {
+var Style = Base.extend(new function() {
 	// windingRule / resolution / fillOverprint / strokeOverprint are currently
 	// not supported.
 	var defaults = {
@@ -201,7 +201,7 @@ var Style = this.Style = Base.extend(new function() {
 	Item.inject(item);
 	return fields;
 }, /** @lends Style# */{
-	initialize: function(style) {
+	initialize: function Style(style) {
 		// We keep values in a separate object that we can iterate over.
 		this._values = {};
 		if (this._item instanceof TextItem)
@@ -223,9 +223,9 @@ var Style = this.Style = Base.extend(new function() {
 		}
 	},
 
-	getLeading: function() {
+	getLeading: function getLeading() {
 		// Override leading to return fontSize * 1.2 by default.
-		var leading = this.base();
+		var leading = getLeading.base.call(this);
 		return leading != null ? leading : this.getFontSize() * 1.2;
 	},
 
diff --git a/src/svg/SVGExport.js b/src/svg/SVGExport.js
index c2743b9c..053173b0 100644
--- a/src/svg/SVGExport.js
+++ b/src/svg/SVGExport.js
@@ -122,10 +122,10 @@ new function() {
 			if (handle1.isOrthogonal(handle2)) {
 				var from = segment._point,
 					to = next._point,
-					// Find hte corner point by intersecting the lines described
+					// Find the corner point by intersecting the lines described
 					// by both handles:
-					corner = new Line(from, handle1).intersect(
-							new Line(to, handle2));
+					corner = new Line(from, handle1, true).intersect(
+							new Line(to, handle2, true), true);
 				return corner && Numerical.isZero(handle1.getLength() /
 						corner.subtract(from).getLength() - kappa)
 					&& Numerical.isZero(handle2.getLength() /
diff --git a/src/svg/SVGImport.js b/src/svg/SVGImport.js
index e48c7f82..769b0463 100644
--- a/src/svg/SVGImport.js
+++ b/src/svg/SVGImport.js
@@ -44,14 +44,14 @@ new function() {
 		x = getValue(node, x, false, allowNull);
 		y = getValue(node, y, false, allowNull);
 		return allowNull && x == null && y == null ? null
-				: Point.create(x || 0, y || 0);
+				: new Point(x || 0, y || 0);
 	}
 
 	function getSize(node, w, h, allowNull) {
 		w = getValue(node, w, false, allowNull);
 		h = getValue(node, h, false, allowNull);
 		return allowNull && w == null && h == null ? null
-				: Size.create(w || 0, h || 0);
+				: new Size(w || 0, h || 0);
 	}
 
 	// Converts a string attribute value to the specified type
@@ -383,7 +383,8 @@ new function() {
 
 		'stop-color': function(item, value) {
 			// http://www.w3.org/TR/SVG/pservers.html#StopColorProperty
-			item.setColor(value);
+			if (item.setColor)
+				item.setColor(value);
 		},
 
 		'stop-opacity': function(item, value) {
diff --git a/src/text/PointText.js b/src/text/PointText.js
index 77617d98..b6fcded9 100644
--- a/src/text/PointText.js
+++ b/src/text/PointText.js
@@ -19,9 +19,7 @@
  *
  * @extends TextItem
  */
-var PointText = this.PointText = TextItem.extend(/** @lends PointText# */{
-	_class: 'PointText',
-
+var PointText = TextItem.extend(/** @lends PointText# */{
 	/**
 	 * Creates a point text item
 	 *
@@ -43,6 +41,9 @@ var PointText = this.PointText = TextItem.extend(/** @lends PointText# */{
 	 * 	fontSize: 25
 	 * });
 	 */
+	initialize: function PointText() {
+		TextItem.apply(this, arguments);
+	},
 
 	clone: function() {
 		return this._clone(new PointText());
@@ -109,7 +110,7 @@ var PointText = this.PointText = TextItem.extend(/** @lends PointText# */{
 				x -= width / (justification === 'center' ? 2: 1);
 			// Until we don't have baseline measuring, assume leading / 4 as a
 			// rough guess:
-			var bounds = Rectangle.create(x,
+			var bounds = new Rectangle(x,
 						count ? leading / 4 + (count - 1) * leading : 0,
 						width, -count * leading);
 			return matrix ? matrix._transformBounds(bounds, bounds) : bounds;
diff --git a/src/text/TextItem.js b/src/text/TextItem.js
index 91986253..2cf907f6 100644
--- a/src/text/TextItem.js
+++ b/src/text/TextItem.js
@@ -21,7 +21,7 @@
  *
  * @extends Item
  */
-var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{
+var TextItem = Item.extend(/** @lends TextItem# */{
 	_boundsSelected: true,
 	_serializeFields: {
 		content: null
@@ -30,7 +30,7 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{
 	// so use the same name for all of them
 	_boundsGetter: 'getBounds',
 
-	initialize: function(arg) {
+	initialize: function TextItem(arg) {
 		// Support two forms of item initialization: Passing one object literal
 		// describing all the different properties to be set, or a point where
 		// it should be placed (arg).
@@ -38,7 +38,7 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{
 		// might be a properties object literal for #setPropeties() at the end.
 		var hasProperties = arg && Base.isPlainObject(arg)
 				&& arg.x === undefined && arg.y === undefined;
-		this.base(hasProperties ? null : Point.read(arguments));
+		Item.call(this, hasProperties ? null : Point.read(arguments));
 		this._content = '';
 		this._lines = [];
 		if (hasProperties)
@@ -77,9 +77,9 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{
 	 * }
 	 */
 
-	_clone: function(copy) {
+	_clone: function _clone(copy) {
 		copy.setContent(this._content);
-		return this.base(copy);
+		return _clone.base.call(this, copy);
 	},
 
 	getContent: function() {
diff --git a/src/tool/Tool.js b/src/tool/Tool.js
index fbdc2dfb..17e3ed04 100644
--- a/src/tool/Tool.js
+++ b/src/tool/Tool.js
@@ -42,7 +42,7 @@
  * 	path.add(event.point);
  * }
  */
-var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{
+var Tool = PaperScopeItem.extend(/** @lends Tool# */{
 	_list: 'tools',
 	_reference: '_tool', // PaperScope has accessor for #tool
 	_events: [ 'onActivate', 'onDeactivate', 'onEditOptions',
@@ -50,8 +50,8 @@ var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{
 			'onKeyDown', 'onKeyUp' ],
 
 	// DOCS: rewrite Tool constructor explanation
-	initialize: function(props) {
-		this.base();
+	initialize: function Tool(props) {
+		PaperScopeItem.call(this);
 		this._firstMove = true;
 		this._count = 0;
 		this._downCount = 0;
@@ -322,7 +322,7 @@ var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{
 		return true;
 	},
 
-	fire: function(type, event) {
+	fire: function fire(type, event) {
 		// Override Callback#fire() so we can handle items marked in removeOn*()
 		// calls first,.
 		var sets = Tool._removeSets;
@@ -346,7 +346,7 @@ var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{
 				sets[type] = null;
 			}
 		}
-		return this.base(type, event);
+		return fire.base.call(this, type, event);
 	},
 
 	_onHandleEvent: function(type, point, event) {
diff --git a/src/tool/ToolEvent.js b/src/tool/ToolEvent.js
index 72c0fead..644ae70a 100644
--- a/src/tool/ToolEvent.js
+++ b/src/tool/ToolEvent.js
@@ -21,11 +21,11 @@
  *
  * @extends Event
  */
-var ToolEvent = this.ToolEvent = Event.extend(/** @lends ToolEvent# */{
+var ToolEvent = Event.extend(/** @lends ToolEvent# */{
 	// Have ToolEvent#item fall back to returning null, not undefined.
 	_item: null,
 
-	initialize: function(tool, type, event) {
+	initialize: function ToolEvent(tool, type, event) {
 		this.tool = tool;
 		this.type = type;
 		this.event = event;
diff --git a/src/ui/CanvasView.js b/src/ui/CanvasView.js
index 077f2b1e..6e4aa8ed 100644
--- a/src/ui/CanvasView.js
+++ b/src/ui/CanvasView.js
@@ -22,19 +22,19 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
 	 * @param {HTMLCanvasElement} canvas The canvas object that this view should
 	 * wrap
 	 */
-	initialize: function(canvas) {
+	initialize: function CanvasView(canvas) {
 		// Handle canvas argument
 		if (!(canvas instanceof HTMLCanvasElement)) {
 			// 2nd argument onwards could be view size, otherwise use default:
 			var size = Size.read(arguments, 1);
 			if (size.isZero())
-				size = Size.create(1024, 768);
+				size = new Size(1024, 768);
 			canvas = CanvasProvider.getCanvas(size);
 		}
 		this._context = canvas.getContext('2d');
 		// Have Item count installed mouse events.
 		this._eventCounters = {};
-		this.base(canvas);
+		View.call(this, canvas);
 	},
 
 	/**
@@ -44,7 +44,7 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
 	 * @function
 	 */
 	draw: function(checkRedraw) {
-		if (checkRedraw && !this._redrawNeeded)
+		if (checkRedraw && !this._project._needsRedraw)
 			return false;
 		// Initial tests conclude that clearing the canvas using clearRect
 		// is always faster than setting canvas.width = canvas.width
@@ -53,7 +53,7 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
 			size = this._viewSize;
 		ctx.clearRect(0, 0, size._width + 1, size._height + 1);
 		this._project.draw(ctx, this._matrix);
-		this._redrawNeeded = false;
+		this._project._needsRedraw = false;
 		return true;
 	}
 }, new function() { // Item based mouse handling:
@@ -169,8 +169,8 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
 	};
 });
 
-/*#*/ if (options.server) {
-// Node.js server based image exporting code.
+/*#*/ if (options.node) {
+// Node.js based image exporting code.
 CanvasView.inject(new function() {
 	// Utility function that converts a number to a string with
 	// x amount of padded 0 digits:
@@ -252,4 +252,4 @@ CanvasView.inject(new function() {
 		}
 	};
 });
-/*#*/ } // options.server
+/*#*/ } // options.node
diff --git a/src/ui/Component.js b/src/ui/Component.js
index 845df744..1ceda35b 100644
--- a/src/ui/Component.js
+++ b/src/ui/Component.js
@@ -14,7 +14,7 @@
   * @name Component
   * @class
   */
-var Component = this.Component = Base.extend(Callback, /** @lends Component# */{
+var Component = Base.extend(Callback, /** @lends Component# */{
 	_events: [ 'onChange', 'onClick' ],
 
 	_types: {
@@ -58,7 +58,7 @@ var Component = this.Component = Base.extend(Callback, /** @lends Component# */{
 		}
 	},
 
-	initialize: function(obj) {
+	initialize: function Component(obj) {
 		this._type = obj.type in this._types
 			? obj.type
 			: 'options' in obj
diff --git a/src/ui/Event.js b/src/ui/Event.js
index 0001c7db..e4d38e5d 100644
--- a/src/ui/Event.js
+++ b/src/ui/Event.js
@@ -14,8 +14,8 @@
  * @name Event
  * @class
  */
-var Event = this.Event = Base.extend(/** @lends Event# */{
-	initialize: function(event) {
+var Event = Base.extend(/** @lends Event# */{
+	initialize: function Event(event) {
 		this.event = event;
 	},
 
diff --git a/src/ui/Key.js b/src/ui/Key.js
index 9332f2f0..da9e5609 100644
--- a/src/ui/Key.js
+++ b/src/ui/Key.js
@@ -14,7 +14,7 @@
  * @name Key
  * @namespace
  */
-var Key = this.Key = new function() {
+var Key = new function() {
 	// TODO: Make sure the keys are called the same as in Scriptographer
 	// Missing: tab, cancel, clear, page-down, page-up, comma, minus, period,
 	// slash, etc etc etc.
diff --git a/src/ui/KeyEvent.js b/src/ui/KeyEvent.js
index c1dcecec..a38f2efb 100644
--- a/src/ui/KeyEvent.js
+++ b/src/ui/KeyEvent.js
@@ -20,9 +20,9 @@
  *
  * @extends Event
  */
-var KeyEvent = this.KeyEvent = Event.extend(/** @lends KeyEvent# */{
-	initialize: function(down, key, character, event) {
-		this.base(event);
+var KeyEvent = Event.extend(/** @lends KeyEvent# */{
+	initialize: function KeyEvent(down, key, character, event) {
+		Event.call(this, event);
 		this.type = down ? 'keydown' : 'keyup';
 		this.key = key;
 		this.character = character;
diff --git a/src/ui/MouseEvent.js b/src/ui/MouseEvent.js
index a520e51b..64f32684 100644
--- a/src/ui/MouseEvent.js
+++ b/src/ui/MouseEvent.js
@@ -22,9 +22,9 @@
  *
  * @extends Event
  */
-var MouseEvent = this.MouseEvent = Event.extend(/** @lends MouseEvent# */{
-	initialize: function(type, event, point, target, delta) {
-		this.base(event);
+var MouseEvent = Event.extend(/** @lends MouseEvent# */{
+	initialize: function MouseEvent(type, event, point, target, delta) {
+		Event.call(this, event);
 		this.type = type;
 		this.point = point;
 		this.target = target;
diff --git a/src/ui/Palette.js b/src/ui/Palette.js
index f2cbb936..bc1f888a 100644
--- a/src/ui/Palette.js
+++ b/src/ui/Palette.js
@@ -14,10 +14,10 @@
   * @name Palette
   * @class
   */
-var Palette = this.Palette = Base.extend(Callback, /** @lends Palette# */{
+var Palette = Base.extend(Callback, /** @lends Palette# */{
 	_events: [ 'onChange' ],
 
-	initialize: function(title, components, values) {
+	initialize: function Palette(title, components, values) {
 		var parent = DomElement.find('.palettejs-panel')
 			|| DomElement.find('body').appendChild(
 				DomElement.create('div', { 'class': 'palettejs-panel' }));
@@ -49,7 +49,6 @@ var Palette = this.Palette = Base.extend(Callback, /** @lends Palette# */{
 				Base.define(values, name, {
 					enumerable: true,
 					configurable: true,
-					writable: true,
 					get: function() {
 						return component._value;
 					},
diff --git a/src/ui/View.js b/src/ui/View.js
index ea3307f5..8be7b943 100644
--- a/src/ui/View.js
+++ b/src/ui/View.js
@@ -19,8 +19,8 @@
  * center, both useful for constructing artwork that should appear centered on
  * screen.
  */
-var View = this.View = Base.extend(Callback, /** @lends View# */{
-	initialize: function(element) {
+var View = Base.extend(Callback, /** @lends View# */{
+	initialize: function View(element) {
 		// Store reference to the currently active global paper scope, and the
 		// active project, which will be represented by this view
 		this._scope = paper;
@@ -60,7 +60,7 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{
 			// If the element is invisible, we cannot directly access
 			// element.width / height, because they would appear 0.
 			// Reading the attributes still works.
-			size = Size.create(parseInt(element.getAttribute('width'), 10),
+			size = new Size(parseInt(element.getAttribute('width'), 10),
 						parseInt(element.getAttribute('height'), 10));
 			// If no size was specified on the canvas, read it from CSS
 			if (size.isNaN())
@@ -83,11 +83,11 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{
 			style.top = offset.y + 'px';
 			document.body.appendChild(stats);
 		}
-/*#*/ } else if (options.server) {
+/*#*/ } else if (options.node) {
 		// Generate an id for this view
 		this._id = 'view-' + View._id++;
-		size = Size.create(element.width, element.height);
-/*#*/ } // options.server
+		size = new Size(element.width, element.height);
+/*#*/ } // options.node
 		// Keep track of views internally
 		View._views.push(this);
 		// Link this id to our view
@@ -235,7 +235,7 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{
 	},
 
 	_redraw: function() {
-		this._redrawNeeded = true;
+		this._project._needsRedraw = true;
 		if (this._handlingFrame)
 			return;
 		if (this._animate) {
diff --git a/src/util/Formatter.js b/src/util/Formatter.js
index d9261d1a..d26069b5 100644
--- a/src/util/Formatter.js
+++ b/src/util/Formatter.js
@@ -30,6 +30,8 @@ var Formatter = Base.extend({
 	 * @param {Number} num the number to be converted to a string
 	 */
 	number: function(val) {
+		// It would be nice to use Number#toFixed() instead, but it pads with 0,
+		// unecessarily consuming space.
 		return Math.round(val * this.multiplier) / this.multiplier;
 	},
 
diff --git a/src/util/Numerical.js b/src/util/Numerical.js
index 08d44bda..db04302a 100644
--- a/src/util/Numerical.js
+++ b/src/util/Numerical.js
@@ -10,7 +10,7 @@
  * All rights reserved.
  */
 
-var Numerical = this.Numerical = new function() {
+var Numerical = new function() {
 
 	// Lookup tables for abscissas and weights with values for n = 2 .. 16.
 	// As values are symetric, only store half of them and addapt algorithm