Version 0.4.4.2
svn merge -r 20688:20748 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@20761 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/scheduled_test/lib/scheduled_test.dart b/pkg/scheduled_test/lib/scheduled_test.dart
index 4c4eed1..b46dc45 100644
--- a/pkg/scheduled_test/lib/scheduled_test.dart
+++ b/pkg/scheduled_test/lib/scheduled_test.dart
@@ -183,7 +183,7 @@
export 'package:unittest/matcher.dart' hide completes, completion;
export 'package:unittest/unittest.dart' show
- config, configure, Configuration, logMessage, expectThrow;
+ Configuration, logMessage, expectThrow;
export 'src/schedule.dart';
export 'src/schedule_error.dart';
@@ -344,3 +344,10 @@
return currentSchedule.wrapFuture(future, description);
}
+
+// TODO(nweiz): re-export these once issue 9535 is fixed.
+unittest.Configuration get unittestConfiguration =>
+ unittest.unittestConfiguration;
+void set unittestConfiguration(unittest.Configuration value) {
+ unittest.unittestConfiguration = value;
+}
diff --git a/pkg/scheduled_test/test/descriptor_test.dart b/pkg/scheduled_test/test/descriptor_test.dart
index baca328..f43e159 100644
--- a/pkg/scheduled_test/test/descriptor_test.dart
+++ b/pkg/scheduled_test/test/descriptor_test.dart
@@ -17,6 +17,12 @@
String sandbox;
void main() {
+ metaSetUp(() {
+ // The windows bots are very slow, so we increase the default timeout.
+ if (Platform.operatingSystem != "windows") return;
+ currentSchedule.timeout = new Duration(seconds: 10);
+ });
+
expectTestsPass('file().create() creates a file', () {
test('test', () {
scheduleSandbox();
diff --git a/pkg/scheduled_test/test/metatest.dart b/pkg/scheduled_test/test/metatest.dart
index 0771ff4..71ad421 100644
--- a/pkg/scheduled_test/test/metatest.dart
+++ b/pkg/scheduled_test/test/metatest.dart
@@ -15,6 +15,7 @@
import 'package:pathos/path.dart' as path;
import 'package:unittest/unittest.dart';
+import 'package:scheduled_test/scheduled_test.dart' as scheduled_test;
import 'utils.dart';
@@ -71,6 +72,14 @@
});
}
+/// Runs [setUpFn] before every metatest. Note that [setUpFn] will be
+/// overwritten if the test itself calls [setUp].
+void metaSetUp(void setUpFn()) {
+ _inChildIsolate.then((inIsolate) {
+ if (inIsolate) scheduled_test.setUp(setUpFn);
+ });
+}
+
/// Sets up a test with the given [description] and [body]. After the test runs,
/// calls [validate] with the result map.
void _setUpTest(String description, void body(), void validate(Map)) {
diff --git a/pkg/scheduled_test/test/scheduled_process_test.dart b/pkg/scheduled_test/test/scheduled_process_test.dart
index 9742947..4b89da1 100644
--- a/pkg/scheduled_test/test/scheduled_process_test.dart
+++ b/pkg/scheduled_test/test/scheduled_process_test.dart
@@ -16,6 +16,12 @@
import 'utils.dart';
void main() {
+ metaSetUp(() {
+ // The windows bots are very slow, so we increase the default timeout.
+ if (Platform.operatingSystem != "windows") return;
+ currentSchedule.timeout = new Duration(seconds: 10);
+ });
+
expectTestsPass("a process must have kill() or shouldExit() called", () {
var errors;
test('test 1', () {
diff --git a/pkg/scheduled_test/test/scheduled_server_test.dart b/pkg/scheduled_test/test/scheduled_server_test.dart
index 19135e0..b34765c 100644
--- a/pkg/scheduled_test/test/scheduled_server_test.dart
+++ b/pkg/scheduled_test/test/scheduled_server_test.dart
@@ -16,6 +16,12 @@
import 'utils.dart';
void main() {
+ metaSetUp(() {
+ // The windows bots are very slow, so we increase the default timeout.
+ if (Platform.operatingSystem != "windows") return;
+ currentSchedule.timeout = new Duration(seconds: 10);
+ });
+
expectTestsPass("a server with no handlers does nothing", () {
test('test', () => new ScheduledServer());
});
diff --git a/pkg/scheduled_test/test/scheduled_test_test.dart b/pkg/scheduled_test/test/scheduled_test_test.dart
index b3c8477..b1c0acb 100644
--- a/pkg/scheduled_test/test/scheduled_test_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test_test.dart
@@ -5,6 +5,7 @@
library scheduled_test_test;
import 'dart:async';
+import 'dart:io';
import 'package:scheduled_test/scheduled_test.dart';
import 'package:scheduled_test/src/mock_clock.dart' as mock_clock;
@@ -13,6 +14,12 @@
import 'utils.dart';
void main() {
+ metaSetUp(() {
+ // The windows bots are very slow, so we increase the default timeout.
+ if (Platform.operatingSystem != "windows") return;
+ currentSchedule.timeout = new Duration(seconds: 10);
+ });
+
expectTestsPass('a scheduled test with a correct synchronous expectation '
'should pass', () {
test('test', () {
diff --git a/pkg/stack_trace/lib/src/frame.dart b/pkg/stack_trace/lib/src/frame.dart
index fdf4fe0..5f0777c 100644
--- a/pkg/stack_trace/lib/src/frame.dart
+++ b/pkg/stack_trace/lib/src/frame.dart
@@ -9,6 +9,7 @@
import 'package:pathos/path.dart' as path;
import 'trace.dart';
+import 'utils.dart';
final _nativeFrameRegExp = new RegExp(
r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$');
@@ -42,7 +43,7 @@
String get library {
// TODO(nweiz): handle relative URIs here as well once pathos supports that.
if (uri.scheme != 'file') return uri.toString();
- return path.relative(uri.path);
+ return path.relative(fileUriToPath(uri));
}
/// A human-friendly description of the code location.
diff --git a/pkg/stack_trace/lib/src/utils.dart b/pkg/stack_trace/lib/src/utils.dart
new file mode 100644
index 0000000..790dec8
--- /dev/null
+++ b/pkg/stack_trace/lib/src/utils.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library utils;
+
+import 'dart:io';
+import 'dart:uri';
+
+import 'package:pathos/path.dart' as path;
+
+/// Converts a `file:` [Uri] to a local path string.
+String fileUriToPath(Uri uri) {
+ if (uri.scheme != 'file') {
+ throw new ArgumentError("Uri $uri must have scheme 'file:'.");
+ }
+ if (Platform.operatingSystem != 'windows') return uri.path;
+ return uri.path.replaceFirst("/", "").replaceAll("/", "\\");
+}
+
+/// Converts a local path string to a `file:` [Uri].
+Uri pathToFileUri(String pathString) {
+ pathString = path.absolute(pathString);
+ if (Platform.operatingSystem != 'windows') {
+ return Uri.parse('file://$pathString');
+ } else {
+ return Uri.parse('file:///${pathString.replaceAll("\\", "/")}');
+ }
+}
diff --git a/pkg/stack_trace/test/frame_test.dart b/pkg/stack_trace/test/frame_test.dart
index 5c5a32e..c65f395 100644
--- a/pkg/stack_trace/test/frame_test.dart
+++ b/pkg/stack_trace/test/frame_test.dart
@@ -8,6 +8,7 @@
import 'dart:uri';
import 'package:pathos/path.dart' as path;
+import 'package:stack_trace/src/utils.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:unittest/unittest.dart';
@@ -42,7 +43,7 @@
// TODO(nweiz): use URL-style paths when such a thing exists.
var builder = new path.Builder(style: path.Style.posix);
expect(builder.basename(frame.uri.path), equals('frame_test.dart'));
- expect(frame.line, equals(16));
+ expect(frame.line, equals(17));
expect(frame.column, equals(5));
expect(frame.member, equals('getStackFrame'));
});
@@ -113,7 +114,7 @@
});
test('returns the relative path for file URIs', () {
- var uri = _pathToFileUri(path.join('foo', 'bar.dart'));
+ var uri = pathToFileUri(path.join('foo', 'bar.dart'));
expect(new Frame.parse('#0 Foo ($uri:0:0)').library,
equals(path.join('foo', 'bar.dart')));
});
@@ -125,7 +126,7 @@
expect(new Frame.parse('#0 Foo '
'(http://dartlang.org/thing.dart:5:10)').location,
equals('http://dartlang.org/thing.dart 5:10'));
- var uri = _pathToFileUri(path.join('foo', 'bar.dart'));
+ var uri = pathToFileUri(path.join('foo', 'bar.dart'));
expect(new Frame.parse('#0 Foo ($uri:1:2)').location,
equals('${path.join('foo', 'bar.dart')} 1:2'));
});
@@ -158,9 +159,3 @@
});
});
}
-
-String _pathToFileUri(String pathString) {
- pathString = path.absolute(pathString);
- if (Platform.operatingSystem != 'windows') return 'file://$pathString';
- return 'file:///${pathString.replaceAll("\\", "/")}';
-}
diff --git a/pkg/stack_trace/test/trace_test.dart b/pkg/stack_trace/test/trace_test.dart
index 2cbe48d..ed8fa6b 100644
--- a/pkg/stack_trace/test/trace_test.dart
+++ b/pkg/stack_trace/test/trace_test.dart
@@ -8,6 +8,7 @@
import 'dart:uri';
import 'package:pathos/path.dart' as path;
+import 'package:stack_trace/src/utils.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:unittest/unittest.dart';
@@ -91,7 +92,7 @@
});
test('.toString() nicely formats the stack trace', () {
- var uri = _pathToFileUri(path.join('foo', 'bar.dart'));
+ var uri = pathToFileUri(path.join('foo', 'bar.dart'));
var trace = new Trace.parse('''
#0 Foo._bar ($uri:42:21)
#1 zip.<anonymous closure>.zap (dart:async:0:2)
@@ -133,9 +134,3 @@
'''));
});
}
-
-String _pathToFileUri(String pathString) {
- pathString = path.absolute(pathString);
- if (Platform.operatingSystem != 'windows') return 'file://$pathString';
- return 'file:///${pathString.replaceAll("\\", "/")}';
-}
diff --git a/pkg/unittest/test/unittest_test.dart b/pkg/unittest/test/unittest_test.dart
index 9621d92..7f62c50 100644
--- a/pkg/unittest/test/unittest_test.dart
+++ b/pkg/unittest/test/unittest_test.dart
@@ -14,6 +14,10 @@
import 'dart:async';
import 'package:unittest/unittest.dart';
+var tests; // array of test names
+var expected; // array of test expected results (from buildStatusString)
+var actual; // actual test results (from buildStatusString in config.onDone)
+
Future _defer(void fn()) {
return new Future.of(fn);
}
@@ -67,7 +71,7 @@
}
runTest() {
- port.receive((String testName, sendport) {
+ port.receive((testName, sendport) {
var _testconfig= new TestConfiguration(sendport);
unittestConfiguration = _testconfig;
@@ -299,34 +303,63 @@
});
}
+void nextTest(int testNum) {
+ SendPort sport = spawnFunction(runTest);
+ sport.call(tests[testNum]).then((msg) {
+ actual.add(msg);
+ if (actual.length == expected.length) {
+ for (var i = 0; i < tests.length; i++) {
+ test(tests[i], () => expect(actual[i].trim(), equals(expected[i])));
+ }
+ } else {
+ nextTest(testNum+1);
+ }
+ });
+}
+
main() {
- var tests = {
- 'single correct test': buildStatusString(1, 0, 0, 'single correct test'),
- 'single failing test': buildStatusString(0, 1, 0, 'single failing test',
+ tests = [
+ 'single correct test',
+ 'single failing test',
+ 'exception test',
+ 'group name test',
+ 'setup test',
+ 'teardown test',
+ 'setup and teardown test',
+ 'correct callback test',
+ 'excess callback test',
+ 'completion test',
+ 'async exception test',
+ 'late exception test',
+ 'middle exception test',
+ 'async setup/teardown test',
+ 'test returning future',
+ 'test returning future using Timer',
+ 'testCases immutable'
+ ];
+
+ expected = [
+ buildStatusString(1, 0, 0, tests[0]),
+ buildStatusString(0, 1, 0, tests[1],
message: 'Expected: <5> but: was <4>.'),
- 'exception test': buildStatusString(0, 1, 0, 'exception test',
- message: 'Caught Exception: Fail.'),
- 'group name test': buildStatusString(2, 0, 0, 'a a::a b b'),
- 'setup test': buildStatusString(1, 0, 0, 'a setup test',
- count: 0, setup: 'setup'),
- 'teardown test': buildStatusString(1, 0, 0, 'a teardown test',
- count: 0, setup: '', teardown: 'teardown'),
- 'setup and teardown test': buildStatusString(1, 0, 0,
- 'a setup and teardown test', count: 0, setup: 'setup',
+ buildStatusString(0, 1, 0, tests[2], message: 'Caught Exception: Fail.'),
+ buildStatusString(2, 0, 0, 'a a::a b b'),
+ buildStatusString(1, 0, 0, 'a ${tests[4]}', count: 0, setup: 'setup'),
+ buildStatusString(1, 0, 0, 'a ${tests[5]}', count: 0, setup: '',
teardown: 'teardown'),
- 'correct callback test': buildStatusString(1, 0, 0, 'correct callback test',
- count: 1),
- 'excess callback test': buildStatusString(0, 1, 0, 'excess callback test',
- count: 1, message: 'Callback called more times than expected (1).'),
- 'completion test': buildStatusString(1, 0, 0, 'completion test', count: 10),
- 'async exception test': buildStatusString(0, 1, 0, 'async exception test',
- message: 'Caught error!'),
- 'late exception test': buildStatusString(1, 0, 1, 'testOne',
+ buildStatusString(1, 0, 0, 'a ${tests[6]}', count: 0,
+ setup: 'setup', teardown: 'teardown'),
+ buildStatusString(1, 0, 0, tests[7], count: 1),
+ buildStatusString(0, 1, 0, tests[8], count: 1,
+ message: 'Callback called more times than expected (1).'),
+ buildStatusString(1, 0, 0, tests[9], count: 10),
+ buildStatusString(0, 1, 0, tests[10], message: 'Caught error!'),
+ buildStatusString(1, 0, 1, 'testOne',
message: 'Callback called (2) after test case testOne has already '
'been marked as pass.:testTwo:'),
- 'middle exception test': buildStatusString(2, 1, 0,
+ buildStatusString(2, 1, 0,
'testOne::testTwo:Expected: false but: was <true>.:testThree'),
- 'async setup/teardown test': buildStatusString(2, 0, 3,
+ buildStatusString(2, 0, 3,
'good setup/good teardown foo1::'
'good setup/bad teardown foo2:good setup/bad teardown '
'foo2: Test teardown failed: Failed to complete tearDown:'
@@ -335,28 +368,25 @@
'bad setup/bad teardown foo4:bad setup/bad teardown '
'foo4: Test teardown failed: Failed to complete tearDown:'
'post groups'),
- 'test returning future': buildStatusString(2, 4, 0,
+ buildStatusString(2, 4, 0,
'successful::'
'error1:Callback called more times than expected (1).:'
'fail1:Expected: <false> but: was <true>.:'
'error2:Callback called more times than expected (1).:'
'fail2:failure:'
'foo5'),
- 'test returning future using Timer': buildStatusString(2, 4, 0,
+ buildStatusString(2, 4, 0,
'successful::'
'fail1:Expected: <false> but: was <true>.:'
'error1:Callback called more times than expected (1).:'
'fail2:failure:'
'error2:Callback called more times than expected (1).:'
'foo6'),
- 'testCases immutable':
- buildStatusString(1, 0, 0, 'testCases immutable'),
- };
+ buildStatusString(1, 0, 0, 'testCases immutable'),
+ ];
- tests.forEach((String name, String expected) {
- test(name, () => spawnFunction(runTest)
- .call(name)
- .then((String msg) => expect(msg.trim(), equals(expected))));
- });
+ actual = [];
+
+ nextTest(0);
}
diff --git a/runtime/embedders/openglui/android/android_input_handler.h b/runtime/embedders/openglui/android/android_input_handler.h
index d1e8d2a..420e459 100644
--- a/runtime/embedders/openglui/android/android_input_handler.h
+++ b/runtime/embedders/openglui/android/android_input_handler.h
@@ -5,7 +5,6 @@
#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_
#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_
-#include "embedders/openglui/android/android_sensor.h"
#include "embedders/openglui/common/graphics_handler.h"
#include "embedders/openglui/common/input_handler.h"
diff --git a/runtime/embedders/openglui/android/android_sound_handler.cc b/runtime/embedders/openglui/android/android_sound_handler.cc
index a40c1ba..de9e977 100644
--- a/runtime/embedders/openglui/android/android_sound_handler.cc
+++ b/runtime/embedders/openglui/android/android_sound_handler.cc
@@ -19,7 +19,6 @@
sample_player_(NULL),
sample_player_if_(NULL),
sample_player_queue_(NULL) {
- SoundHandler::instance_ = this;
}
int32_t AndroidSoundHandler::Start() {
diff --git a/runtime/embedders/openglui/android/main.cc b/runtime/embedders/openglui/android/main.cc
index 4844a3d..c0c386b 100644
--- a/runtime/embedders/openglui/android/main.cc
+++ b/runtime/embedders/openglui/android/main.cc
@@ -5,7 +5,6 @@
#include "embedders/openglui/android/android_graphics_handler.h"
#include "embedders/openglui/android/android_input_handler.h"
#include "embedders/openglui/android/android_resource.h"
-#include "embedders/openglui/android/android_sensor.h"
#include "embedders/openglui/android/android_sound_handler.h"
#include "embedders/openglui/android/eventloop.h"
#include "embedders/openglui/common/context.h"
diff --git a/runtime/embedders/openglui/common/gl.dart b/runtime/embedders/openglui/common/gl.dart
index 084338c..f709000 100644
--- a/runtime/embedders/openglui/common/gl.dart
+++ b/runtime/embedders/openglui/common/gl.dart
@@ -576,143 +576,143 @@
//------------------------------------------------------------------
// 2D canvas support
-int SetWidth(int handle, int width)
- native "CanvasSetWidth";
-int SetHeight(int handle, int height)
- native "CanvasSetHeight";
+int _SetWidth(int handle, int width)
+ native "C2DSetWidth";
+int _SetHeight(int handle, int height)
+ native "C2DSetHeight";
-double SetGlobalAlpha(int handle, double globalAlpha)
- native "CanvasSetGlobalAlpha";
-void SetFillStyle(int handle, fs)
- native "CanvasSetFillStyle";
-String SetFont(int handle, String font)
- native "CanvasSetFont";
-void SetGlobalCompositeOperation(int handle, String op)
- native "CanvasSetGlobalCompositeOperation";
-SetLineCap(int handle, String lc)
- native "CanvasSetLineCap";
-SetLineJoin(int handle, String lj)
- native "CanvasSetLineJoin";
-SetLineWidth(int handle, double w)
- native "CanvasSetLineWidth";
-SetMiterLimit(int handle, double limit)
- native "CanvasSetMiterLimit";
-SetShadowBlur(int handle, double blur)
- native "CanvasSetShadowBlur";
-SetShadowColor(int handle, String color)
- native "CanvasSetShadowColor";
-SetShadowOffsetX(int handle, double offset)
- native "CanvasSetShadowOffsetX";
-SetShadowOffsetY(int handle, double offset)
- native "CanvasSetShadowOffsetY";
-void SetStrokeStyle(int handle, ss)
- native "CanvasSetStrokeStyle";
-String SetTextAlign(int handle, String align)
- native "CanvasSetTextAlign";
-String SetTextBaseline(int handle, String baseline)
- native "CanvasSetTextBaseline";
-GetBackingStorePixelRatio(int handle)
- native "CanvasGetBackingStorePixelRatio";
-void SetImageSmoothingEnabled(int handle, bool ise)
- native "CanvasSetImageSmoothingEnabled";
-void SetLineDash(int handle, List v)
- native "CanvasSetLineDash";
-SetLineDashOffset(int handle, int v)
- native "CanvasSetLineDashOffset";
-void Arc(int handle, double x, double y, double radius,
+double _SetGlobalAlpha(int handle, double globalAlpha)
+ native "C2DSetGlobalAlpha";
+void _SetFillStyle(int handle, fs)
+ native "C2DSetFillStyle";
+String _SetFont(int handle, String font)
+ native "C2DSetFont";
+void _SetGlobalCompositeOperation(int handle, String op)
+ native "C2DSetGlobalCompositeOperation";
+_SetLineCap(int handle, String lc)
+ native "C2DSetLineCap";
+_SetLineJoin(int handle, String lj)
+ native "C2DSetLineJoin";
+_SetLineWidth(int handle, double w)
+ native "C2DSetLineWidth";
+_SetMiterLimit(int handle, double limit)
+ native "C2DSetMiterLimit";
+_SetShadowBlur(int handle, double blur)
+ native "C2DSetShadowBlur";
+_SetShadowColor(int handle, String color)
+ native "C2DSetShadowColor";
+_SetShadowOffsetX(int handle, double offset)
+ native "C2DSetShadowOffsetX";
+_SetShadowOffsetY(int handle, double offset)
+ native "C2DSetShadowOffsetY";
+void _SetStrokeStyle(int handle, ss)
+ native "C2DSetStrokeStyle";
+String _SetTextAlign(int handle, String align)
+ native "C2DSetTextAlign";
+String _SetTextBaseline(int handle, String baseline)
+ native "C2DSetTextBaseline";
+_GetBackingStorePixelRatio(int handle)
+ native "C2DGetBackingStorePixelRatio";
+void _SetImageSmoothingEnabled(int handle, bool ise)
+ native "C2DSetImageSmoothingEnabled";
+void _SetLineDash(int handle, List v)
+ native "C2DSetLineDash";
+_SetLineDashOffset(int handle, int v)
+ native "C2DSetLineDashOffset";
+void _Arc(int handle, double x, double y, double radius,
double startAngle, double endAngle, [bool anticlockwise = false])
- native "CanvasArc";
-void ArcTo(int handle, double x1, double y1,
+ native "C2DArc";
+void _ArcTo(int handle, double x1, double y1,
double x2, double y2, double radius)
- native "CanvasArcTo";
-void ArcTo2(int handle, double x1, double y1,
+ native "C2DArcTo";
+void _ArcTo2(int handle, double x1, double y1,
double x2, double y2, double radiusX,
double radiusY, double rotation)
- native "CanvasArcTo2";
-void BeginPath(int handle)
- native "CanvasBeginPath";
-void BezierCurveTo(int handle, double cp1x, double cp1y,
+ native "C2DArcTo2";
+void _BeginPath(int handle)
+ native "C2DBeginPath";
+void _BezierCurveTo(int handle, double cp1x, double cp1y,
double cp2x, double cp2y, double x, double y)
- native "CanvasBezierCurveTo";
-void ClearRect(int handle, double x, double y, double w, double h)
- native "CanvasClearRect";
-void Clip(int handle)
- native "CanvasClip";
-void ClosePath(int handle)
- native "CanvasClosePath";
-ImageData CreateImageDataFromDimensions(int handle, num w, num h)
- native "CanvasCreateImageDataFromDimensions";
-void DrawImage(int handle, String src_url,
+ native "C2DBezierCurveTo";
+void _ClearRect(int handle, double x, double y, double w, double h)
+ native "C2DClearRect";
+void _Clip(int handle)
+ native "C2DClip";
+void _ClosePath(int handle)
+ native "C2DClosePath";
+ImageData _CreateImageDataFromDimensions(int handle, num w, num h)
+ native "C2DCreateImageDataFromDimensions";
+void _DrawImage(int handle, String src_url,
int sx, int sy,
bool has_src_dimensions, int sw, int sh,
int dx, int dy,
bool has_dst_dimensions, int dw, int dh)
- native "CanvasDrawImage";
-void Fill(int handle)
- native "CanvasFill";
-void FillRect(int handle, double x, double y, double w, double h)
- native "CanvasFillRect";
-void FillText(int handle, String text, double x, double y, double maxWidth)
- native "CanvasFillText";
-ImageData GetImageData(num sx, num sy, num sw, num sh)
- native "CanvasGetImageData";
-void LineTo(int handle, double x, double y)
- native "CanvasLineTo";
-double MeasureText(int handle, String text)
- native "CanvasMeasureText";
-void MoveTo(int handle, double x, double y)
- native "CanvasMoveTo";
-void PutImageData(int handle, ImageData imagedata, double dx, double dy)
- native "CanvasPutImageData";
-void QuadraticCurveTo(int handle, double cpx, double cpy,
+ native "C2DDrawImage";
+void _Fill(int handle)
+ native "C2DFill";
+void _FillRect(int handle, double x, double y, double w, double h)
+ native "C2DFillRect";
+void _FillText(int handle, String text, double x, double y, double maxWidth)
+ native "C2DFillText";
+ImageData _GetImageData(num sx, num sy, num sw, num sh)
+ native "C2DGetImageData";
+void _LineTo(int handle, double x, double y)
+ native "C2DLineTo";
+double _MeasureText(int handle, String text)
+ native "C2DMeasureText";
+void _MoveTo(int handle, double x, double y)
+ native "C2DMoveTo";
+void _PutImageData(int handle, ImageData imagedata, double dx, double dy)
+ native "C2DPutImageData";
+void _QuadraticCurveTo(int handle, double cpx, double cpy,
double x, double y)
- native "CanvasQuadraticCurveTo";
-void Rect(int handle, double x, double y, double w, double h)
- native "CanvasRect";
-void Restore(int handle)
- native "CanvasRestore";
-void Rotate(int handle, double a)
- native "CanvasRotate";
-void Save(int handle)
- native "CanvasSave";
-void Scale(int handle, double sx, double sy)
- native "CanvasScale";
-void SetTransform(int handle, double m11, double m12,
+ native "C2DQuadraticCurveTo";
+void _Rect(int handle, double x, double y, double w, double h)
+ native "C2DRect";
+void _Restore(int handle)
+ native "C2DRestore";
+void _Rotate(int handle, double a)
+ native "C2DRotate";
+void _Save(int handle)
+ native "C2DSave";
+void _Scale(int handle, double sx, double sy)
+ native "C2DScale";
+void _SetTransform(int handle, double m11, double m12,
double m21, double m22, double dx, double dy)
- native "CanvasSetTransform";
-void Stroke(int handle)
- native "CanvasStroke";
-void StrokeRect(int handle, double x, double y, double w, double h)
- native "CanvasStrokeRect";
-void StrokeText(int handle, String text, double x, double y,
+ native "C2DSetTransform";
+void _Stroke(int handle)
+ native "C2DStroke";
+void _StrokeRect(int handle, double x, double y, double w, double h)
+ native "C2DStrokeRect";
+void _StrokeText(int handle, String text, double x, double y,
double maxWidth)
- native "CanvasStrokeText";
-void Transform(int handle, double m11, double m12,
+ native "C2DStrokeText";
+void _Transform(int handle, double m11, double m12,
double m21, double m22, double dx, double dy)
- native "CanvasTransform";
-void Translate(int handle, double x, double y)
- native "CanvasTranslate";
+ native "C2DTransform";
+void _Translate(int handle, double x, double y)
+ native "C2DTranslate";
-void CreateNativeContext(int handle, int width, int height)
- native "CanvasCreateNativeContext";
+void _CreateNativeContext(int handle, int width, int height)
+ native "C2DCreateNativeContext";
-void SetFillGradient(int handle, bool isRadial,
+void _SetFillGradient(int handle, bool isRadial,
double x0, double y0, double r0,
double x1, double y1, double r1,
List<double> positions, List<String> colors)
- native "CanvasSetFillGradient";
+ native "C2DSetFillGradient";
-void SetStrokeGradient(int handle, bool isRadial,
+void _SetStrokeGradient(int handle, bool isRadial,
double x0, double y0, double r0,
double x1, double y1, double r1,
List<double> positions, List<String> colors)
- native "CanvasSetStrokeGradient";
+ native "C2DSetStrokeGradient";
-int GetImageWidth(String url)
- native "CanvasGetImageWidth";
+int _GetImageWidth(String url)
+ native "C2DGetImageWidth";
-int GetImageHeight(String url)
- native "CanvasGetImageHeight";
+int _GetImageHeight(String url)
+ native "C2DGetImageHeight";
class CanvasGradient {
num _x0, _y0, _r0 = 0, _x1, _y1, _r1 = 0;
@@ -733,14 +733,14 @@
: _isRadial = true;
void setAsFillStyle(_handle) {
- SetFillGradient(_handle, _isRadial,
+ _SetFillGradient(_handle, _isRadial,
_x0.toDouble(), _y0.toDouble(), _r0.toDouble(),
_x1.toDouble(), _y1.toDouble(), _r1.toDouble(),
_colorStopPositions, _colorStopColors);
}
void setAsStrokeStyle(_handle) {
- SetStrokeGradient(_handle, _isRadial,
+ _SetStrokeGradient(_handle, _isRadial,
_x0.toDouble(), _y0.toDouble(), _r0.toDouble(),
_x1.toDouble(), _y1.toDouble(), _r1.toDouble(),
_colorStopPositions, _colorStopColors);
@@ -772,8 +772,8 @@
}
}
- get width => _width == null ? _width = GetImageWidth(_src) : _width;
- get height => _height == null ? _height = GetImageHeight(_src) : _height;
+ get width => _width == null ? _width = _GetImageWidth(_src) : _width;
+ get height => _height == null ? _height = _GetImageHeight(_src) : _height;
set width(int widthp) => _width = widthp;
set height(int heightp) => _height = heightp;
@@ -782,8 +782,8 @@
_width = widthp,
_height = heightp {
if (_src != null) {
- if (_width == null) _width = GetImageWidth(_src);
- if (_height == null) _height = GetImageHeight(_src);
+ if (_width == null) _width = _GetImageWidth(_src);
+ if (_height == null) _height = _GetImageHeight(_src);
}
}
}
@@ -826,12 +826,12 @@
CanvasRenderingContext2D(canvas, width, height) : super(canvas) {
_width = width;
_height = height;
- CreateNativeContext(_handle = next_handle++, width, height);
+ _CreateNativeContext(_handle = next_handle++, width, height);
}
double _alpha = 1.0;
set globalAlpha(num a) {
- _alpha = SetGlobalAlpha(_handle, a.toDouble());
+ _alpha = _SetGlobalAlpha(_handle, a.toDouble());
}
get globalAlpha => _alpha;
@@ -844,46 +844,46 @@
if (fs is CanvasGradient) {
fs.setAsFillStyle(_handle);
} else {
- SetFillStyle(_handle, fs);
+ _SetFillStyle(_handle, fs);
}
}
get fillStyle => _fillStyle;
String _font = "10px sans-serif";
- set font(String f) { _font = SetFont(_handle, f); }
+ set font(String f) { _font = _SetFont(_handle, f); }
get font => _font;
String _globalCompositeOperation = "source-over";
set globalCompositeOperation(String o) =>
- SetGlobalCompositeOperation(_handle, _globalCompositeOperation = o);
+ _SetGlobalCompositeOperation(_handle, _globalCompositeOperation = o);
get globalCompositeOperation => _globalCompositeOperation;
String _lineCap = "butt"; // "butt", "round", "square"
get lineCap => _lineCap;
- set lineCap(String lc) => SetLineCap(_handle, _lineCap = lc);
+ set lineCap(String lc) => _SetLineCap(_handle, _lineCap = lc);
int _lineDashOffset = 0;
get lineDashOffset => _lineDashOffset;
set lineDashOffset(num v) {
_lineDashOffset = v.toInt();
- SetLineDashOffset(_handle, _lineDashOffset);
+ _SetLineDashOffset(_handle, _lineDashOffset);
}
String _lineJoin = "miter"; // "round", "bevel", "miter"
get lineJoin => _lineJoin;
- set lineJoin(String lj) => SetLineJoin(_handle, _lineJoin = lj);
+ set lineJoin(String lj) => _SetLineJoin(_handle, _lineJoin = lj);
num _lineWidth = 1.0;
get lineWidth => _lineWidth;
set lineWidth(num w) {
- SetLineWidth(_handle, w.toDouble());
+ _SetLineWidth(_handle, w.toDouble());
_lineWidth = w;
}
num _miterLimit = 10.0; // (default 10)
get miterLimit => _miterLimit;
set miterLimit(num limit) {
- SetMiterLimit(_handle, limit.toDouble());
+ _SetMiterLimit(_handle, limit.toDouble());
_miterLimit = limit;
}
@@ -891,26 +891,26 @@
get shadowBlur => _shadowBlur;
set shadowBlur(num blur) {
_shadowBlur = blur;
- SetShadowBlur(_handle, blur.toDouble());
+ _SetShadowBlur(_handle, blur.toDouble());
}
String _shadowColor;
get shadowColor => _shadowColor;
set shadowColor(String color) =>
- SetShadowColor(_handle, _shadowColor = color);
+ _SetShadowColor(_handle, _shadowColor = color);
num _shadowOffsetX;
get shadowOffsetX => _shadowOffsetX;
set shadowOffsetX(num offset) {
_shadowOffsetX = offset;
- SetShadowOffsetX(_handle, offset.toDouble());
+ _SetShadowOffsetX(_handle, offset.toDouble());
}
num _shadowOffsetY;
get shadowOffsetY => _shadowOffsetY;
set shadowOffsetY(num offset) {
_shadowOffsetY = offset;
- SetShadowOffsetY(_handle, offset.toDouble());
+ _SetShadowOffsetY(_handle, offset.toDouble());
}
var _strokeStyle = "#000";
@@ -921,24 +921,24 @@
if (ss is CanvasGradient) {
ss.setAsStrokeStyle(_handle);
} else {
- SetStrokeStyle(_handle, ss);
+ _SetStrokeStyle(_handle, ss);
}
}
String _textAlign = "start";
get textAlign => _textAlign;
- set textAlign(String a) { _textAlign = SetTextAlign(_handle, a); }
+ set textAlign(String a) { _textAlign = _SetTextAlign(_handle, a); }
String _textBaseline = "alphabetic";
get textBaseline => _textBaseline;
- set textBaseline(String b) { _textBaseline = SetTextBaseline(_handle, b); }
+ set textBaseline(String b) { _textBaseline = _SetTextBaseline(_handle, b); }
- get webkitBackingStorePixelRatio => GetBackingStorePixelRatio(_handle);
+ get webkitBackingStorePixelRatio => _GetBackingStorePixelRatio(_handle);
bool _webkitImageSmoothingEnabled;
get webkitImageSmoothingEnabled => _webkitImageSmoothingEnabled;
set webkitImageSmoothingEnabled(bool v) =>
- SetImageSmoothingEnabled(_webkitImageSmoothingEnabled = v);
+ _SetImageSmoothingEnabled(_webkitImageSmoothingEnabled = v);
get webkitLineDash => lineDash;
set webkitLineDash(List v) => lineDash = v;
@@ -952,7 +952,7 @@
if (radius < 0) {
// throw IndexSizeError
} else {
- Arc(_handle, x.toDouble(), y.toDouble(), radius.toDouble(),
+ _Arc(_handle, x.toDouble(), y.toDouble(), radius.toDouble(),
a1.toDouble(), a2.toDouble(), anticlockwise);
}
}
@@ -962,37 +962,37 @@
void arcTo(num x1, num y1, num x2, num y2,
num radiusX, [num radiusY, num rotation]) {
if (radiusY == null) {
- ArcTo(_handle, x1.toDouble(), y1.toDouble(),
+ _ArcTo(_handle, x1.toDouble(), y1.toDouble(),
x2.toDouble(), y2.toDouble(), radiusX.toDouble());
} else {
- ArcTo2(_handle, x1.toDouble(), y1.toDouble(),
+ _ArcTo2(_handle, x1.toDouble(), y1.toDouble(),
x2.toDouble(), y2.toDouble(),
radiusX.toDouble(), radiusY.toDouble(),
rotation.toDouble());
}
}
- void beginPath() => BeginPath(_handle);
+ void beginPath() => _BeginPath(_handle);
void bezierCurveTo(num cp1x, num cp1y, num cp2x, num cp2y,
num x, num y) =>
- BezierCurveTo(_handle, cp1x.toDouble(), cp1y.toDouble(),
+ _BezierCurveTo(_handle, cp1x.toDouble(), cp1y.toDouble(),
cp2x.toDouble(), cp2y.toDouble(),
x.toDouble(), y.toDouble());
void clearRect(num x, num y, num w, num h) =>
- ClearRect(_handle, x.toDouble(), y.toDouble(),
+ _ClearRect(_handle, x.toDouble(), y.toDouble(),
w.toDouble(), h.toDouble());
- void clip() => Clip(_handle);
+ void clip() => _Clip(_handle);
- void closePath() => ClosePath(_handle);
+ void closePath() => _ClosePath(_handle);
ImageData createImageData(var imagedata_OR_sw, [num sh = null]) {
if (sh == null) {
throw new Exception('Unimplemented createImageData(imagedata)');
} else {
- return CreateImageDataFromDimensions(_handle, imagedata_OR_sw, sh);
+ return _CreateImageDataFromDimensions(_handle, imagedata_OR_sw, sh);
}
}
@@ -1009,7 +1009,7 @@
return new CanvasGradient.radial(x0, y0, r0, x1, y1, r1);
}
- void drawImage(element, num x1, num y1,
+ void _drawImage(element, num x1, num y1,
[num w1, num h1, num x2, num y2, num w2, num h2]) {
if (element == null || element.src == null || element.src.length == 0) {
throw "drawImage called with no valid src";
@@ -1019,40 +1019,56 @@
var w = (element.width == null) ? 0 : element.width;
var h = (element.height == null) ? 0 : element.height;
if (!?w1) { // drawImage(element, dx, dy)
- DrawImage(_handle, element.src, 0, 0, false, w, h,
+ _DrawImage(_handle, element.src, 0, 0, false, w, h,
x1.toInt(), y1.toInt(), false, 0, 0);
} else if (!?x2) { // drawImage(element, dx, dy, dw, dh)
- DrawImage(_handle, element.src, 0, 0, false, w, h,
+ _DrawImage(_handle, element.src, 0, 0, false, w, h,
x1.toInt(), y1.toInt(), true, w1.toInt(), h1.toInt());
} else { // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
- DrawImage(_handle, element.src,
+ _DrawImage(_handle, element.src,
x1.toInt(), y1.toInt(), true, w1.toInt(), h1.toInt(),
x2.toInt(), y2.toInt(), true, w2.toInt(), h2.toInt());
}
}
- void drawImageAtScale(element, Rect dest, {Rect sourceRect}) {
+ void drawImage(source, num destX, num destY) {
+ _drawImage(source, destX, destY);
+ }
+
+ void drawImageScaled(source,
+ num destX, num destY, num destWidth, num destHeight) {
+ _drawImage(source, destX, destY, destWidth, destHeight);
+ }
+
+ void drawImageScaledFromSource(source,
+ num sourceX, num sourceY, num sourceWidth, num sourceHeight,
+ num destX, num destY, num destWidth, num destHeight) {
+ _drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight,
+ destX, destY, destWidth, destHeight);
+ }
+
+ void drawImageToRect(source, Rect dest, {Rect sourceRect}) {
if (sourceRect == null) {
- drawImage(element, dest.left, dest.top, dest.width, dest.height);
+ _drawImage(source, dest.left, dest.top, dest.width, dest.height);
} else {
- drawImage(element,
+ _drawImage(source,
sourceRect.left, sourceRect.top, sourceRect.width, sourceRect.height,
dest.left, dest.top, dest.width, dest.height);
}
}
- void fill() => Fill(_handle);
+ void fill() => _Fill(_handle);
void fillRect(num x, num y, num w, num h) =>
- FillRect(_handle, x.toDouble(), y.toDouble(),
+ _FillRect(_handle, x.toDouble(), y.toDouble(),
w.toDouble(), h.toDouble());
void fillText(String text, num x, num y, [num maxWidth = -1]) =>
- FillText(_handle, text, x.toDouble(), y.toDouble(),
+ _FillText(_handle, text, x.toDouble(), y.toDouble(),
maxWidth.toDouble());
ImageData getImageData(num sx, num sy, num sw, num sh) =>
- GetImageData(sx, sy, sw, sh);
+ _GetImageData(sx, sy, sw, sh);
List<double> _lineDash = null;
List<num> getLineDash() {
@@ -1065,40 +1081,40 @@
}
void lineTo(num x, num y) {
- LineTo(_handle, x.toDouble(), y.toDouble());
+ _LineTo(_handle, x.toDouble(), y.toDouble());
}
TextMetrics measureText(String text) {
- double w = MeasureText(_handle, text);
+ double w = _MeasureText(_handle, text);
return new TextMetrics(w);
}
void moveTo(num x, num y) =>
- MoveTo(_handle, x.toDouble(), y.toDouble());
+ _MoveTo(_handle, x.toDouble(), y.toDouble());
void putImageData(ImageData imagedata, num dx, num dy,
[num dirtyX, num dirtyY, num dirtyWidth, num dirtyHeight]) {
if (dirtyX != null || dirtyY != null) {
throw new Exception('Unimplemented putImageData');
} else {
- PutImageData(_handle, imagedata, dx, dy);
+ _PutImageData(_handle, imagedata, dx, dy);
}
}
void quadraticCurveTo(num cpx, num cpy, num x, num y) =>
- QuadraticCurveTo(_handle, cpx.toDouble(), cpy.toDouble(),
+ _QuadraticCurveTo(_handle, cpx.toDouble(), cpy.toDouble(),
x.toDouble(), y.toDouble());
void rect(num x, num y, num w, num h) =>
- Rect(_handle, x.toDouble(), y.toDouble(), w.toDouble(), h.toDouble());
+ _Rect(_handle, x.toDouble(), y.toDouble(), w.toDouble(), h.toDouble());
- void restore() => Restore(_handle);
+ void restore() => _Restore(_handle);
- void rotate(num angle) => Rotate(_handle, angle.toDouble());
+ void rotate(num angle) => _Rotate(_handle, angle.toDouble());
- void save() => Save(_handle);
+ void save() => _Save(_handle);
- void scale(num x, num y) => Scale(_handle, x.toDouble(), y.toDouble());
+ void scale(num x, num y) => _Scale(_handle, x.toDouble(), y.toDouble());
void setFillColorHsl(int h, num s, num l, [num a = 1]) {
throw new Exception('Unimplemented setFillColorHsl');
@@ -1133,7 +1149,7 @@
}
}
if (valid) {
- SetLineDash(_handle, _lineDash = new_dash);
+ _SetLineDash(_handle, _lineDash = new_dash);
}
}
@@ -1146,27 +1162,27 @@
}
void setTransform(num m11, num m12, num m21, num m22, num dx, num dy) =>
- SetTransform(_handle, m11.toDouble(), m12.toDouble(),
- m21.toDouble(), m22.toDouble(),
- dx.toDouble(), dy.toDouble());
+ _SetTransform(_handle, m11.toDouble(), m12.toDouble(),
+ m21.toDouble(), m22.toDouble(),
+ dx.toDouble(), dy.toDouble());
- void stroke() => Stroke(_handle);
+ void stroke() => _Stroke(_handle);
void strokeRect(num x, num y, num w, num h, [num lineWidth]) =>
- StrokeRect(_handle, x.toDouble(), y.toDouble(),
+ _StrokeRect(_handle, x.toDouble(), y.toDouble(),
w.toDouble(), h.toDouble());
void strokeText(String text, num x, num y, [num maxWidth = -1]) =>
- StrokeText(_handle, text, x.toDouble(), y.toDouble(),
- maxWidth.toDouble());
+ _StrokeText(_handle, text, x.toDouble(), y.toDouble(),
+ maxWidth.toDouble());
void transform(num m11, num m12, num m21, num m22, num dx, num dy) =>
- Transform(_handle, m11.toDouble(), m12.toDouble(),
- m21.toDouble(), m22.toDouble(),
- dx.toDouble(), dy.toDouble());
+ _Transform(_handle, m11.toDouble(), m12.toDouble(),
+ m21.toDouble(), m22.toDouble(),
+ dx.toDouble(), dy.toDouble());
void translate(num x, num y) =>
- Translate(_handle, x.toDouble(), y.toDouble());
+ _Translate(_handle, x.toDouble(), y.toDouble());
ImageData webkitGetImageDataHD(num sx, num sy, num sw, num sh) {
throw new Exception('Unimplemented webkitGetImageDataHD');
@@ -1184,5 +1200,6 @@
}
}
+var sfx_extension = 'raw';
int _loadSample(String s) native "LoadSample";
int _playSample(String s) native "PlaySample";
diff --git a/runtime/embedders/openglui/common/image_cache.cc b/runtime/embedders/openglui/common/image_cache.cc
index f6c1be5..957f7ea 100644
--- a/runtime/embedders/openglui/common/image_cache.cc
+++ b/runtime/embedders/openglui/common/image_cache.cc
@@ -18,7 +18,6 @@
}
const SkBitmap* ImageCache::GetImage_(const char* src_url) {
-fprintf(stderr, "ImageCache::GetImage(%s)\n", src_url);
if (strncmp(src_url, "context2d://", 12) == 0) {
int handle = atoi(src_url + 12);
CanvasContext* otherContext = Context2D(handle);
@@ -35,21 +34,18 @@
}
int ImageCache::GetWidth_(const char* src_url) {
-fprintf(stderr, "ImageCache::GetWidth(%s)\n", src_url);
const SkBitmap* image = GetImage(src_url);
if (image == NULL) return 0;
return image->width();
}
int ImageCache::GetHeight_(const char* src_url) {
-fprintf(stderr, "ImageCache::GetHeight(%s)\n", src_url);
const SkBitmap* image = GetImage(src_url);
if (image == NULL) return 0;
return image->height();
}
SkBitmap* ImageCache::Load(const char* src_url) {
-fprintf(stderr, "ImageCache::Load(%s)\n", src_url);
SkBitmap *bm = NULL;
const char* filepath;
if (strncmp(src_url, "file://", 7) == 0) {
diff --git a/runtime/embedders/openglui/common/vm_glue.cc b/runtime/embedders/openglui/common/vm_glue.cc
index 4b7bccd..77564e54 100644
--- a/runtime/embedders/openglui/common/vm_glue.cc
+++ b/runtime/embedders/openglui/common/vm_glue.cc
@@ -24,14 +24,16 @@
VMGlue::VMGlue(ISized* surface,
const char* script_path,
const char* extension_script,
- const char* main_script)
+ const char* main_script,
+ int setup_flag)
: surface_(surface),
isolate_(NULL),
initialized_script_(false),
x_(0.0),
y_(0.0),
z_(0.0),
- accelerometer_changed_(false) {
+ accelerometer_changed_(false),
+ setup_flag_(setup_flag) {
LOGI("Creating VMGlue");
if (main_script == NULL) {
main_script = "main.dart";
@@ -207,14 +209,16 @@
// we can eliminate it along with the need for the force parameter.
if (!initialized_script_ || force) {
initialized_script_ = true;
- LOGI("Invoking setup(NULL, %d,%d)", surface_->width(), surface_->height());
+ LOGI("Invoking setup(null, %d,%d,%d)",
+ surface_->width(), surface_->height(), setup_flag_);
Dart_EnterIsolate(isolate_);
Dart_EnterScope();
- Dart_Handle args[3];
+ Dart_Handle args[4];
args[0] = CheckError(Dart_Null());
args[1] = CheckError(Dart_NewInteger(surface_->width()));
args[2] = CheckError(Dart_NewInteger(surface_->height()));
- int rtn = Invoke("setup", 3, args);
+ args[3] = CheckError(Dart_NewInteger(setup_flag_));
+ int rtn = Invoke("setup", 4, args);
if (rtn == 0) {
// Plug in the print handler. It would be nice if we could do this
diff --git a/runtime/embedders/openglui/common/vm_glue.h b/runtime/embedders/openglui/common/vm_glue.h
index cf7788f..f340b56 100644
--- a/runtime/embedders/openglui/common/vm_glue.h
+++ b/runtime/embedders/openglui/common/vm_glue.h
@@ -16,7 +16,8 @@
explicit VMGlue(ISized* surface,
const char* script_path,
const char* extension_script = NULL,
- const char* main_script = NULL);
+ const char* main_script = NULL,
+ int setup_flag = 0);
~VMGlue() {
delete[] main_script_;
delete[] extension_script_;
@@ -70,6 +71,7 @@
char* main_script_;
float x_, y_, z_; // Last values from accelerometer.
bool accelerometer_changed_;
+ int setup_flag_;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_VM_GLUE_H_
diff --git a/runtime/embedders/openglui/emulator/emulator_embedder.cc b/runtime/embedders/openglui/emulator/emulator_embedder.cc
index 904a60f..de01870 100644
--- a/runtime/embedders/openglui/emulator/emulator_embedder.cc
+++ b/runtime/embedders/openglui/emulator/emulator_embedder.cc
@@ -104,7 +104,7 @@
script = argv[i];
}
}
- VMGlue vm_glue(&graphics_handler, ".", "gl.dart", script);
+ VMGlue vm_glue(&graphics_handler, ".", "gl.dart", script, 1);
InputHandler input_handler(&vm_glue);
input_handler_ptr = &input_handler;
SoundHandler sound_handler;
diff --git a/runtime/embedders/openglui/openglui_embedder.gypi b/runtime/embedders/openglui/openglui_embedder.gypi
index 2893fbe..dc66642 100644
--- a/runtime/embedders/openglui/openglui_embedder.gypi
+++ b/runtime/embedders/openglui/openglui_embedder.gypi
@@ -247,16 +247,16 @@
'-Wall',
'<(skia_libs_location_desktop)',
'-Wl,--start-group',
- '-lskia_effects',
- '-lskia_images',
'-lskia_core',
+ '-lskia_effects',
+ '-lskia_gr',
+ '-lskia_images',
'-lskia_opts',
'-lskia_opts_ssse3',
'-lskia_ports',
'-lskia_sfnt',
- '-lskia_utils',
- '-lskia_gr',
'-lskia_skgr',
+ '-lskia_utils',
'-Wl,--end-group',
'-lfreetype',
],
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index 8bc87cc..b98cc4b 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -76,6 +76,27 @@
}
+void Assembler::LoadObject(Register rd, const Object& object) {
+ // Smi's and VM heap objects are never relocated; do not use object pool.
+ if (object.IsSmi()) {
+ LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()));
+ } else if (object.InVMHeap()) {
+ // Make sure that class CallPattern is able to decode this load immediate.
+ int32_t object_raw = reinterpret_cast<int32_t>(object.raw());
+ const uint16_t object_low = Utils::Low16Bits(object_raw);
+ const uint16_t object_high = Utils::High16Bits(object_raw);
+ lui(rd, Immediate(object_high));
+ ori(rd, rd, Immediate(object_low));
+ } else {
+ // Make sure that class CallPattern is able to decode this load from the
+ // object pool.
+ const int32_t offset =
+ Array::data_offset() + 4*AddObject(object) - kHeapObjectTag;
+ LoadWordFromPoolOffset(rd, offset);
+ }
+}
+
+
int32_t Assembler::AddObject(const Object& obj) {
ASSERT(obj.IsNotTemporaryScopedHandle());
ASSERT(obj.IsOld());
@@ -94,6 +115,92 @@
}
+void Assembler::PushObject(const Object& object) {
+ LoadObject(TMP, object);
+ Push(TMP);
+}
+
+
+void Assembler::CompareObject(Register rd, Register rn, const Object& object) {
+ ASSERT(rn != TMP);
+ LoadObject(TMP, object);
+ subu(rd, rn, TMP);
+}
+
+
+void Assembler::EnterStubFrame() {
+ addiu(SP, SP, Immediate(-3 * kWordSize));
+ sw(ZR, Address(SP, 2 * kWordSize)); // PC marker is 0 in stubs.
+ sw(RA, Address(SP, 1 * kWordSize));
+ sw(FP, Address(SP, 0 * kWordSize));
+ mov(FP, SP);
+}
+
+
+void Assembler::LeaveStubFrame() {
+ mov(SP, FP);
+ lw(RA, Address(SP, 1 * kWordSize));
+ lw(FP, Address(SP, 0 * kWordSize));
+ addiu(SP, SP, Immediate(3 * kWordSize));
+}
+
+
+void Assembler::EnterDartFrame(intptr_t frame_size) {
+ const intptr_t offset = CodeSize();
+
+ addiu(SP, SP, Immediate(-4 * kWordSize));
+ sw(RA, Address(SP, 2 * kWordSize));
+ sw(FP, Address(SP, 1 * kWordSize));
+ sw(PP, Address(SP, 0 * kWordSize));
+
+ Label next;
+ // Branch and link to the instruction after the delay slot to get the PC.
+ bal(&next);
+
+ // RA is the address of the sw instruction below. Save it in T0.
+ delay_slot()->mov(T0, RA);
+
+ // Calculate the offset of the pool pointer from the PC.
+ const intptr_t object_pool_pc_dist =
+ Instructions::HeaderSize() - Instructions::object_pool_offset() +
+ CodeSize();
+
+ // This sw instruction is the return address for the bal, so T0 holds
+ // the PC at this sw instruction.
+ Bind(&next);
+
+ if (offset != 0) {
+ // Adjust PC for any intrinsic code that could have been generated
+ // before a frame is created.
+ addiu(T0, T0, Immediate(-offset));
+ }
+
+ // Save PC in frame for fast identification of corresponding code.
+ sw(T0, Address(SP, 3 * kWordSize));
+
+ // Set FP to the saved previous FP.
+ addiu(FP, SP, Immediate(kWordSize));
+
+ // Load the pool pointer.
+ lw(PP, Address(T0, -object_pool_pc_dist));
+
+ // Reserve space for locals.
+ addiu(SP, SP, Immediate(-frame_size));
+}
+
+
+void Assembler::LeaveDartFrame() {
+ addiu(SP, FP, Immediate(-kWordSize));
+
+ lw(RA, Address(SP, 2 * kWordSize));
+ lw(FP, Address(SP, 1 * kWordSize));
+ lw(PP, Address(SP, 0 * kWordSize));
+
+ // Adjust SP for PC pushed in EnterDartFrame.
+ addiu(SP, SP, Immediate(4 * kWordSize));
+}
+
+
int32_t Assembler::AddExternalLabel(const ExternalLabel* label) {
if (object_pool_.IsNull()) {
// The object pool cannot be used in the vm isolate.
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 81f9810..68cc734 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -162,18 +162,10 @@
buffer_.FinalizeInstructions(region);
}
- // Set up a Dart frame on entry with a frame pointer and PC information to
- // enable easy access to the RawInstruction object of code corresponding
- // to this frame.
- void EnterDartFrame(intptr_t frame_size) {
- UNIMPLEMENTED();
- }
-
// Set up a stub frame so that the stack traversal code can easily identify
// a stub frame.
- void EnterStubFrame() {
- UNIMPLEMENTED();
- }
+ void EnterStubFrame();
+ void LeaveStubFrame();
// Instruction pattern from entrypoint is used in dart frame prologs
// to set up the frame and save a PC which can be used to figure out the
@@ -250,6 +242,12 @@
beq(R0, R0, l);
}
+ void bal(Label *l) {
+ ASSERT(!in_delay_slot_);
+ EmitRegImmBranch(BGEZAL, R0, l);
+ EmitBranchDelayNop();
+ }
+
// Branch if equal.
void beq(Register rs, Register rt, Label* l) {
ASSERT(!in_delay_slot_);
@@ -546,6 +544,18 @@
jr(TMP);
}
+ // If the signed value in rs is less than value, rd is 1, and 0 otherwise.
+ void LessThanSImmediate(Register rd, Register rs, int32_t value) {
+ LoadImmediate(TMP, value);
+ slt(rd, rs, TMP);
+ }
+
+ // If the unsigned value in rs is less than value, rd is 1, and 0 otherwise.
+ void LessThanUImmediate(Register rd, Register rs, uint32_t value) {
+ LoadImmediate(TMP, value);
+ sltu(rd, rs, TMP);
+ }
+
void Drop(intptr_t stack_elements) {
ASSERT(stack_elements >= 0);
if (stack_elements > 0) {
@@ -578,6 +588,14 @@
jr(RA);
}
+ void SmiTag(Register reg) {
+ sll(reg, reg, kSmiTagSize);
+ }
+
+ void SmiUntag(Register reg) {
+ sra(reg, reg, kSmiTagSize);
+ }
+
void LoadWordFromPoolOffset(Register rd, int32_t offset);
void LoadObject(Register rd, const Object& object);
void PushObject(const Object& object);
@@ -586,6 +604,12 @@
// set to non-zero otherwise.
void CompareObject(Register rd, Register rn, const Object& object);
+ // Set up a Dart frame on entry with a frame pointer and PC information to
+ // enable easy access to the RawInstruction object of code corresponding
+ // to this frame.
+ void EnterDartFrame(intptr_t frame_size);
+ void LeaveDartFrame();
+
private:
AssemblerBuffer buffer_;
GrowableObjectArray& object_pool_; // Objects and patchable jump targets.
diff --git a/runtime/vm/code_generator_test.cc b/runtime/vm/code_generator_test.cc
index cb86ed0..27beef2 100644
--- a/runtime/vm/code_generator_test.cc
+++ b/runtime/vm/code_generator_test.cc
@@ -4,10 +4,6 @@
#include "platform/assert.h"
#include "vm/globals.h"
-#if defined(TARGET_ARCH_IA32) || \
- defined(TARGET_ARCH_X64) || \
- defined(TARGET_ARCH_ARM)
-
#include "vm/ast.h"
#include "vm/assembler.h"
#include "vm/class_finalizer.h"
@@ -38,6 +34,11 @@
CODEGEN_TEST_RUN(SmiReturnCodegen, Smi::New(3))
+#if defined(TARGET_ARCH_IA32) || \
+ defined(TARGET_ARCH_X64) || \
+ defined(TARGET_ARCH_ARM)
+
+
CODEGEN_TEST2_GENERATE(SimpleStaticCallCodegen, function, test) {
// Wrap the SmiReturnCodegen test above as a static function and call it.
ArgumentListNode* no_arguments = new ArgumentListNode(kPos);
@@ -567,6 +568,6 @@
#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
-} // namespace dart
-
#endif // defined(TARGET_ARCH_IA32) || ..._ARCH_X64) || ..._ARCH_ARM)
+
+} // namespace dart
diff --git a/runtime/vm/constants_mips.h b/runtime/vm/constants_mips.h
index db01e25..8b0a266 100644
--- a/runtime/vm/constants_mips.h
+++ b/runtime/vm/constants_mips.h
@@ -141,6 +141,18 @@
const Register FPREG = FP; // Frame pointer register.
+typedef uint32_t RegList;
+const RegList kAllCpuRegistersList = 0xFFFFFFFF;
+
+
+const RegList kAbiArgumentCpuRegs =
+ (1 << A0) | (1 << A1) | (1 << A2) | (1 << A3);
+const RegList kAbiPreservedCpuRegs =
+ (1 << S0) | (1 << S1) | (1 << S2) | (1 << S3) |
+ (1 << S4) | (1 << S5) | (1 << S6) | (1 << S7);
+const int kAbiPreservedCpuRegCount = 8;
+
+
// Dart stack frame layout.
static const int kLastParamSlotIndex = 3;
static const int kFirstLocalSlotIndex = -2;
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index e5d97ed..1045708 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -229,6 +229,7 @@
}
isolate->heap()->EnableGrowthControl();
isolate->set_init_callback_data(data);
+ Api::SetupAcquiredError(isolate);
if (FLAG_print_class_table) {
isolate->class_table()->Print();
}
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 50900ac..1ef5060 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -200,20 +200,20 @@
}
-void Api::SetupCallbackError(Isolate* isolate) {
+void Api::SetupAcquiredError(Isolate* isolate) {
ASSERT(isolate != NULL);
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
- state->SetupCallbackError();
+ state->SetupAcquiredError();
}
-Dart_Handle Api::CallbackError(Isolate* isolate) {
+Dart_Handle Api::AcquiredError(Isolate* isolate) {
ASSERT(isolate != NULL);
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
- PersistentHandle* callback_error_handle = state->CallbackError();
- return reinterpret_cast<Dart_Handle>(callback_error_handle);
+ PersistentHandle* acquired_error_handle = state->AcquiredError();
+ return reinterpret_cast<Dart_Handle>(acquired_error_handle);
}
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 32f36bc..b5e89da 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -106,15 +106,15 @@
// Gets the handle used to designate successful return.
static Dart_Handle Success(Isolate* isolate);
- // Sets up the callback error object after initializing an Isolate. This
+ // Sets up the acquired error object after initializing an Isolate. This
// object is pre-created because we will not be able to allocate this
// object when the error actually occurs. When the error occurs there will
// be outstanding acquires to internal data pointers making it unsafe to
// allocate objects on the dart heap.
- static void SetupCallbackError(Isolate* isolate);
+ static void SetupAcquiredError(Isolate* isolate);
- // Gets the handle which holds the pre-created callback error object.
- static Dart_Handle CallbackError(Isolate* isolate);
+ // Gets the handle which holds the pre-created acquired error object.
+ static Dart_Handle AcquiredError(Isolate* isolate);
// Returns true if the handle holds a Smi.
static bool IsSmi(Dart_Handle handle) {
@@ -192,7 +192,7 @@
#define CHECK_CALLBACK_STATE(isolate) \
if (isolate->no_callback_scope_depth() != 0) { \
- return reinterpret_cast<Dart_Handle>(Api::CallbackError(isolate)); \
+ return reinterpret_cast<Dart_Handle>(Api::AcquiredError(isolate)); \
} \
} // namespace dart.
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index b66ede1..61c4dbc 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -1413,7 +1413,7 @@
}
}
EXPECT(scope == state->top_scope());
- EXPECT_EQ(2000, state->CountPersistentHandles());
+ EXPECT_EQ(2001, state->CountPersistentHandles());
Dart_ShutdownIsolate();
}
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h
index 57e62c0..9b27ecd 100644
--- a/runtime/vm/dart_api_state.h
+++ b/runtime/vm/dart_api_state.h
@@ -527,7 +527,7 @@
public:
ApiState() : top_scope_(NULL), delayed_weak_reference_sets_(NULL),
null_(NULL), true_(NULL), false_(NULL),
- callback_error_(NULL) {}
+ acquired_error_(NULL) {}
~ApiState() {
while (top_scope_ != NULL) {
ApiLocalScope* scope = top_scope_;
@@ -546,6 +546,10 @@
persistent_handles().FreeHandle(false_);
false_ = NULL;
}
+ if (acquired_error_ != NULL) {
+ persistent_handles().FreeHandle(acquired_error_);
+ acquired_error_ = NULL;
+ }
}
// Accessors.
@@ -651,18 +655,13 @@
}
PersistentHandle* Null() {
if (null_ == NULL) {
- DARTSCOPE(Isolate::Current());
-
- Object& null_object = Object::Handle();
null_ = persistent_handles().AllocateHandle();
- null_->set_raw(null_object);
+ null_->set_raw(Object::null());
}
return null_;
}
PersistentHandle* True() {
if (true_ == NULL) {
- DARTSCOPE(Isolate::Current());
-
true_ = persistent_handles().AllocateHandle();
true_->set_raw(Bool::True());
}
@@ -670,25 +669,23 @@
}
PersistentHandle* False() {
if (false_ == NULL) {
- DARTSCOPE(Isolate::Current());
-
false_ = persistent_handles().AllocateHandle();
false_->set_raw(Bool::False());
}
return false_;
}
- void SetupCallbackError() {
- ASSERT(callback_error_ == NULL);
- callback_error_ = persistent_handles().AllocateHandle();
- callback_error_->set_raw(
+ void SetupAcquiredError() {
+ ASSERT(acquired_error_ == NULL);
+ acquired_error_ = persistent_handles().AllocateHandle();
+ acquired_error_->set_raw(
String::New("Internal Dart data pointers have been acquired, "
- "please release them using Dart_ByteArrayReleaseData."));
+ "please release them using Dart_TypedDataReleaseData."));
}
- PersistentHandle* CallbackError() const {
- ASSERT(callback_error_ != NULL);
- return callback_error_;
+ PersistentHandle* AcquiredError() const {
+ ASSERT(acquired_error_ != NULL);
+ return acquired_error_;
}
void DelayWeakReferenceSet(WeakReferenceSet* reference_set) {
@@ -706,7 +703,7 @@
PersistentHandle* null_;
PersistentHandle* true_;
PersistentHandle* false_;
- PersistentHandle* callback_error_;
+ PersistentHandle* acquired_error_;
DISALLOW_COPY_AND_ASSIGN(ApiState);
};
diff --git a/runtime/vm/disassembler_mips.cc b/runtime/vm/disassembler_mips.cc
index ff74333..0c30e3b 100644
--- a/runtime/vm/disassembler_mips.cc
+++ b/runtime/vm/disassembler_mips.cc
@@ -141,7 +141,8 @@
case 'd': {
ASSERT(STRING_STARTS_WITH(format, "dest"));
int off = instr->SImmField() << 2;
- uword destination = reinterpret_cast<uword>(instr) + off;
+ uword destination =
+ reinterpret_cast<uword>(instr) + off + Instr::kInstrSize;
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
remaining_size_in_buffer(),
"%#"Px"",
@@ -377,6 +378,10 @@
Format(instr, "bgez 'rs, 'dest");
break;
}
+ case BGEZAL: {
+ Format(instr, "bgezal 'rs, 'dest");
+ break;
+ }
case BGEZL: {
Format(instr, "bgezl 'rs, 'dest");
break;
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index b455448..1a88c4d 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -7,10 +7,24 @@
#include "vm/flow_graph_compiler.h"
-#include "vm/longjump.h"
+#include "lib/error.h"
+#include "vm/ast_printer.h"
+#include "vm/dart_entry.h"
+#include "vm/il_printer.h"
+#include "vm/locations.h"
+#include "vm/object_store.h"
+#include "vm/parser.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
namespace dart {
+DECLARE_FLAG(int, optimization_counter_threshold);
+DECLARE_FLAG(bool, print_ast);
+DECLARE_FLAG(bool, print_scopes);
+DECLARE_FLAG(bool, enable_type_checks);
+
+
FlowGraphCompiler::~FlowGraphCompiler() {
// BlockInfos are zone-allocated, so their destructors are not called.
// Verify the labels explicitly here.
@@ -31,6 +45,9 @@
}
+#define __ assembler()->
+
+
void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
Label* is_true,
Label* is_false) {
@@ -128,12 +145,24 @@
void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) {
- UNIMPLEMENTED();
+ if (!is_optimizing()) {
+ if (FLAG_enable_type_checks && instr->IsAssertAssignable()) {
+ AssertAssignableInstr* assert = instr->AsAssertAssignable();
+ AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
+ assert->deopt_id(),
+ assert->token_pos());
+ }
+ AllocateRegistersLocally(instr);
+ }
}
void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
- UNIMPLEMENTED();
+ if (is_optimizing()) return;
+ Definition* defn = instr->AsDefinition();
+ if ((defn != NULL) && defn->is_used()) {
+ __ Push(defn->locs()->out().reg());
+ }
}
@@ -153,12 +182,221 @@
void FlowGraphCompiler::EmitFrameEntry() {
- UNIMPLEMENTED();
+ const Function& function = parsed_function().function();
+ if (CanOptimizeFunction() && function.is_optimizable()) {
+ const bool can_optimize = !is_optimizing() || may_reoptimize();
+ const Register function_reg = T0;
+ if (can_optimize) {
+ Label next;
+ // The pool pointer is not setup before entering the Dart frame.
+
+ __ mov(TMP, RA); // Save RA.
+ __ bal(&next); // Branch and link to next instruction to get PC in RA.
+ __ delay_slot()->mov(T2, RA); // Save PC of the following mov.
+
+ // Calculate offset of pool pointer from the PC.
+ const intptr_t object_pool_pc_dist =
+ Instructions::HeaderSize() - Instructions::object_pool_offset() +
+ assembler()->CodeSize();
+
+ __ Bind(&next);
+ __ mov(RA, TMP); // Restore RA.
+
+ // Preserve PP of caller.
+ __ mov(T1, PP);
+
+ // Temporarily setup pool pointer for this dart function.
+ __ lw(PP, Address(T2, -object_pool_pc_dist));
+
+ // Load function object from object pool.
+ __ LoadObject(function_reg, function); // Uses PP.
+
+ // Restore PP of caller.
+ __ mov(PP, T1);
+ }
+ // Patch point is after the eventually inlined function object.
+ AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ if (can_optimize) {
+ // Reoptimization of optimized function is triggered by counting in
+ // IC stubs, but not at the entry of the function.
+ if (!is_optimizing()) {
+ __ lw(T1, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ __ addiu(T1, T1, Immediate(1));
+ __ sw(T1, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ } else {
+ __ lw(T1, FieldAddress(function_reg,
+ Function::usage_counter_offset()));
+ }
+
+ // Skip Branch if T1 is less than the threshold.
+ Label dont_branch;
+ __ LoadImmediate(T2, FLAG_optimization_counter_threshold);
+ __ sltu(T2, T1, T2);
+ __ bgtz(T2, &dont_branch);
+
+ ASSERT(function_reg == T0);
+ __ Branch(&StubCode::OptimizeFunctionLabel());
+
+ __ Bind(&dont_branch);
+ }
+ } else {
+ AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ }
+ __ Comment("Enter frame");
+ __ EnterDartFrame((StackSize() * kWordSize));
}
-
+// Input parameters:
+// RA: return address.
+// SP: address of last argument.
+// FP: caller's frame pointer.
+// PP: caller's pool pointer.
+// S5: ic-data.
+// S4: arguments descriptor array.
void FlowGraphCompiler::CompileGraph() {
- UNIMPLEMENTED();
+ InitCompiler();
+ if (TryIntrinsify()) {
+ // Although this intrinsified code will never be patched, it must satisfy
+ // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum
+ // code size.
+ __ break_(0);
+ __ Branch(&StubCode::FixCallersTargetLabel());
+ return;
+ }
+
+ EmitFrameEntry();
+
+ const Function& function = parsed_function().function();
+
+ const int num_fixed_params = function.num_fixed_parameters();
+ const int num_copied_params = parsed_function().num_copied_params();
+ const int num_locals = parsed_function().num_stack_locals();
+
+ // We check the number of passed arguments when we have to copy them due to
+ // the presence of optional parameters.
+ // No such checking code is generated if only fixed parameters are declared,
+ // unless we are in debug mode or unless we are compiling a closure.
+ LocalVariable* saved_args_desc_var =
+ parsed_function().GetSavedArgumentsDescriptorVar();
+ if (num_copied_params == 0) {
+#ifdef DEBUG
+ ASSERT(!parsed_function().function().HasOptionalParameters());
+ const bool check_arguments = true;
+#else
+ const bool check_arguments = function.IsClosureFunction();
+#endif
+ if (check_arguments) {
+ __ Comment("Check argument count");
+ // Check that exactly num_fixed arguments are passed in.
+ Label correct_num_arguments, wrong_num_arguments;
+ __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
+ __ LoadImmediate(T1, Smi::RawValue(num_fixed_params));
+ __ bne(T0, T1, &wrong_num_arguments);
+
+ __ lw(T1, FieldAddress(S4,
+ ArgumentsDescriptor::positional_count_offset()));
+ __ beq(T0, T1, &correct_num_arguments);
+ __ Bind(&wrong_num_arguments);
+ if (function.IsClosureFunction()) {
+ if (StackSize() != 0) {
+ // We need to unwind the space we reserved for locals and copied
+ // parameters. The NoSuchMethodFunction stub does not expect to see
+ // that area on the stack.
+ __ addiu(SP, SP, Immediate(StackSize() * kWordSize));
+ }
+ // The call below has an empty stackmap because we have just
+ // dropped the spill slots.
+ BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
+
+ // Invoke noSuchMethod function passing "call" as the function name.
+ const int kNumArgsChecked = 1;
+ const ICData& ic_data = ICData::ZoneHandle(
+ ICData::New(function, Symbols::Call(),
+ Isolate::kNoDeoptId, kNumArgsChecked));
+ __ LoadObject(S5, ic_data);
+ // FP - 4 : saved PP, object pool pointer of caller.
+ // FP + 0 : previous frame pointer.
+ // FP + 4 : return address.
+ // FP + 8 : PC marker, for easy identification of RawInstruction obj.
+ // FP + 12: last argument (arg n-1).
+ // SP + 0 : saved PP.
+ // SP + 16 + 4*(n-1) : first argument (arg 0).
+ // S5 : ic-data.
+ // S4 : arguments descriptor array.
+ __ BranchLink(&StubCode::CallNoSuchMethodFunctionLabel());
+ if (is_optimizing()) {
+ stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
+ empty_stack_bitmap,
+ 0); // No registers.
+ }
+ // The noSuchMethod call may return.
+ __ LeaveDartFrame();
+ __ Ret();
+ } else {
+ __ Stop("Wrong number of arguments");
+ }
+ __ Bind(&correct_num_arguments);
+ }
+ // The arguments descriptor is never saved in the absence of optional
+ // parameters, since any argument definition test would always yield true.
+ ASSERT(saved_args_desc_var == NULL);
+ } else {
+ if (saved_args_desc_var != NULL) {
+ __ Comment("Save arguments descriptor");
+ const Register kArgumentsDescriptorReg = S4;
+ // The saved_args_desc_var is allocated one slot before the first local.
+ const intptr_t slot = parsed_function().first_stack_local_index() + 1;
+ // If the saved_args_desc_var is captured, it is first moved to the stack
+ // and later to the context, once the context is allocated.
+ ASSERT(saved_args_desc_var->is_captured() ||
+ (saved_args_desc_var->index() == slot));
+ __ sw(kArgumentsDescriptorReg, Address(FP, slot * kWordSize));
+ }
+ CopyParameters();
+ }
+
+ // In unoptimized code, initialize (non-argument) stack allocated slots to
+ // null. This does not cover the saved_args_desc_var slot.
+ if (!is_optimizing() && (num_locals > 0)) {
+ __ Comment("Initialize spill slots");
+ const intptr_t slot_base = parsed_function().first_stack_local_index();
+ __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
+ for (intptr_t i = 0; i < num_locals; ++i) {
+ // Subtract index i (locals lie at lower addresses than FP).
+ __ sw(T0, Address(FP, (slot_base - i) * kWordSize));
+ }
+ }
+
+ if (FLAG_print_scopes) {
+ // Print the function scope (again) after generating the prologue in order
+ // to see annotations such as allocation indices of locals.
+ if (FLAG_print_ast) {
+ // Second printing.
+ OS::Print("Annotated ");
+ }
+ AstPrinter::PrintFunctionScope(parsed_function());
+ }
+
+ VisitBlocks();
+
+ __ break_(0);
+ GenerateDeferredCode();
+ // Emit function patching code. This will be swapped with the first 5 bytes
+ // at entry point.
+ AddCurrentDescriptor(PcDescriptors::kPatchCode,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ __ Branch(&StubCode::FixCallersTargetLabel());
+ AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump,
+ Isolate::kNoDeoptId,
+ 0); // No token position.
+ __ Branch(&StubCode::DeoptimizeLazyLabel());
}
@@ -183,7 +421,7 @@
intptr_t deopt_id,
const RuntimeEntry& entry,
LocationSummary* locs) {
- UNIMPLEMENTED();
+ __ Unimplemented("call runtime");
}
@@ -252,12 +490,51 @@
void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
- UNIMPLEMENTED();
+ // TODO(vegorov): consider saving only caller save (volatile) registers.
+ const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
+ if (fpu_registers > 0) {
+ UNIMPLEMENTED();
+ }
+
+ // Store general purpose registers with the lowest register number at the
+ // lowest address.
+ const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
+ ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
+ const int register_count = Utils::CountOneBits(cpu_registers);
+ int registers_pushed = 0;
+
+ __ addiu(SP, SP, Immediate(-register_count * kWordSize));
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ Register r = static_cast<Register>(i);
+ if (locs->live_registers()->ContainsRegister(r)) {
+ __ sw(r, Address(SP, registers_pushed * kWordSize));
+ registers_pushed++;
+ }
+ }
}
void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
- UNIMPLEMENTED();
+ // General purpose registers have the lowest register number at the
+ // lowest address.
+ const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
+ ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
+ const int register_count = Utils::CountOneBits(cpu_registers);
+ int registers_popped = 0;
+
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ Register r = static_cast<Register>(i);
+ if (locs->live_registers()->ContainsRegister(r)) {
+ __ lw(r, Address(SP, registers_popped * kWordSize));
+ registers_popped++;
+ }
+ }
+ __ addiu(SP, SP, Immediate(register_count * kWordSize));
+
+ const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
+ if (fpu_registers > 0) {
+ UNIMPLEMENTED();
+ }
}
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 45c00d8..7df257b 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -1768,7 +1768,18 @@
ASSERT(ic_data.num_args_tested() == 1); // Unary checks only.
if (!type.IsInstantiated() || type.IsMalformed()) return Bool::null();
const Class& type_class = Class::Handle(type.type_class());
- if (type_class.HasTypeArguments()) return Bool::null();
+ if (type_class.HasTypeArguments()) {
+ // Only raw types can be directly compared, thus disregarding type
+ // arguments.
+ const AbstractTypeArguments& type_arguments =
+ AbstractTypeArguments::Handle(type.arguments());
+ const bool is_raw_type = type_arguments.IsNull() ||
+ type_arguments.IsRaw(type_arguments.Length());
+ if (!is_raw_type) {
+ // Unknown result.
+ return Bool::null();
+ }
+ }
const ClassTable& class_table = *Isolate::Current()->class_table();
Bool& prev = Bool::Handle();
Class& cls = Class::Handle();
diff --git a/runtime/vm/instructions_mips.cc b/runtime/vm/instructions_mips.cc
index bfc7f1d..a0bc6d4 100644
--- a/runtime/vm/instructions_mips.cc
+++ b/runtime/vm/instructions_mips.cc
@@ -15,16 +15,16 @@
: end_(reinterpret_cast<uword*>(pc)),
target_address_pool_index_(-1),
args_desc_load_end_(-1),
- args_desc_pool_index_(-1),
+ args_desc_(Array::Handle()),
ic_data_load_end_(-1),
- ic_data_pool_index_(-1),
+ ic_data_(ICData::Handle()),
object_pool_(Array::Handle(code.ObjectPool())) {
ASSERT(code.ContainsInstructionAt(pc));
ASSERT(Back(2) == 0x0020f809); // Last instruction: jalr RA, TMP(=R1)
Register reg;
// First end is 0 so that we begin from the delay slot of the jalr.
- args_desc_load_end_ =
- DecodeLoadWordFromPool(2, ®, &target_address_pool_index_);
+ ic_data_load_end_ =
+ DecodeLoadWordFromPool(2, ®, &target_address_pool_index_);
ASSERT(reg == TMP);
}
@@ -35,6 +35,54 @@
}
+// Decodes a load sequence ending at end. Returns the register being loaded and
+// the loaded object.
+// Returns the location of the load sequence, counting the number of
+// instructions back from the end of the call pattern.
+int CallPattern::DecodeLoadObject(int end, Register* reg, Object* obj) {
+ ASSERT(end > 0);
+ uword i = Back(end + 1);
+ Instr* instr = Instr::At(reinterpret_cast<uword>(&i));
+ if (instr->OpcodeField() == LW) {
+ int index = 0;
+ end = DecodeLoadWordFromPool(end, reg, &index);
+ *obj = object_pool_.At(index);
+ } else {
+ int value = 0;
+ end = DecodeLoadWordImmediate(end, reg, &value);
+ *obj = reinterpret_cast<RawObject*>(value);
+ }
+ return end;
+}
+
+
+// Decodes a load sequence ending at end. Returns the register being loaded and
+// the loaded immediate value.
+// Returns the location of the load sequence, counting the number of
+// instructions back from the end of the call pattern.
+int CallPattern::DecodeLoadWordImmediate(int end, Register* reg, int* value) {
+ ASSERT(end > 0);
+ int imm = 0;
+ uword i = Back(++end);
+ Instr* instr = Instr::At(reinterpret_cast<uword>(&i));
+ ASSERT(instr->OpcodeField() == ORI);
+ imm = instr->UImmField();
+ *reg = instr->RtField();
+
+ i = Back(++end);
+ instr = Instr::At(reinterpret_cast<uword>(&i));
+ ASSERT(instr->OpcodeField() == LUI);
+ ASSERT(instr->RtField() == *reg);
+ imm |= instr->UImmField();
+ *value = imm;
+ return end;
+}
+
+
+// Decodes a load sequence ending at end. Returns the register being loaded and
+// the index in the pool being read from.
+// Returns the location of the load sequence, counting the number of
+// instructions back from the end of the call pattern.
int CallPattern::DecodeLoadWordFromPool(int end, Register* reg, int* index) {
ASSERT(end > 0);
uword i = Back(++end);
@@ -58,6 +106,7 @@
i = Back(++end);
instr = Instr::At(reinterpret_cast<uword>(&i));
+ ASSERT(instr->OpcodeField() == LUI);
ASSERT(instr->RtField() == *reg);
// Offset is signed, so add the upper 16 bits.
offset += (instr->UImmField() << 16);
@@ -70,14 +119,23 @@
RawICData* CallPattern::IcData() {
- UNIMPLEMENTED();
- return NULL;
+ if (ic_data_.IsNull()) {
+ Register reg;
+ args_desc_load_end_ = DecodeLoadObject(ic_data_load_end_, ®, &ic_data_);
+ ASSERT(reg == S5);
+ }
+ return ic_data_.raw();
}
RawArray* CallPattern::ArgumentsDescriptor() {
- UNIMPLEMENTED();
- return NULL;
+ if (args_desc_.IsNull()) {
+ IcData(); // Loading of the ic_data must be decoded first, if not already.
+ Register reg;
+ DecodeLoadObject(args_desc_load_end_, ®, &args_desc_);
+ ASSERT(reg == S4);
+ }
+ return args_desc_.raw();
}
diff --git a/runtime/vm/instructions_mips.h b/runtime/vm/instructions_mips.h
index 1a71dc6..4035a3b 100644
--- a/runtime/vm/instructions_mips.h
+++ b/runtime/vm/instructions_mips.h
@@ -27,13 +27,15 @@
private:
uword Back(int n) const;
+ int DecodeLoadObject(int end, Register* reg, Object* obj);
+ int DecodeLoadWordImmediate(int end, Register* reg, int* value);
int DecodeLoadWordFromPool(int end, Register* reg, int* index);
const uword* end_;
int target_address_pool_index_;
int args_desc_load_end_;
- int args_desc_pool_index_;
+ Array& args_desc_;
int ic_data_load_end_;
- int ic_data_pool_index_;
+ ICData& ic_data_;
const Array& object_pool_;
DISALLOW_COPY_AND_ASSIGN(CallPattern);
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index de9556f..6adbda5 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -16,6 +16,8 @@
#include "vm/stub_code.h"
#include "vm/symbols.h"
+#define __ compiler->assembler()->
+
namespace dart {
DECLARE_FLAG(int, optimization_counter_threshold);
@@ -39,13 +41,49 @@
LocationSummary* ReturnInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* locs =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+ locs->set_in(0, Location::RegisterLocation(V0));
+ return locs;
}
+// Attempt optimized compilation at return instruction instead of at the entry.
+// The entry needs to be patchable, no inlined objects are allowed in the area
+// that will be overwritten by the patch instructions: a branch macro sequence.
void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Register result = locs()->in(0).reg();
+ ASSERT(result == V0);
+#if defined(DEBUG)
+ // TODO(srdjan): Fix for functions with finally clause.
+ // A finally clause may leave a previously pushed return value if it
+ // has its own return instruction. Method that have finally are currently
+ // not optimized.
+ if (!compiler->HasFinally()) {
+ Label stack_ok;
+ __ Comment("Stack Check");
+ const int sp_fp_dist = compiler->StackSize() + (-kFirstLocalSlotIndex - 1);
+ __ subu(T2, FP, SP);
+
+ __ addiu(T2, T2, Immediate(-sp_fp_dist * kWordSize));
+ __ beq(T2, ZR, &stack_ok);
+ __ break_(0);
+
+ __ Bind(&stack_ok);
+ }
+#endif
+ __ LeaveDartFrame();
+ __ Ret();
+
+ // Generate 2 NOP instructions so that the debugger can patch the return
+ // pattern (1 instruction) with a call to the debug stub (3 instructions).
+ __ nop();
+ __ nop();
+ compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
+ Isolate::kNoDeoptId,
+ token_pos());
}
@@ -78,13 +116,18 @@
LocationSummary* ConstantInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ return LocationSummary::Make(0,
+ Location::RequiresRegister(),
+ LocationSummary::kNoCall);
}
void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ // The register allocator drops constant definitions that have no uses.
+ if (!locs()->out().IsInvalid()) {
+ Register result = locs()->out().reg();
+ __ LoadObject(result, value());
+ }
}
@@ -386,13 +429,54 @@
LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 0;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs,
+ kNumTemps,
+ LocationSummary::kCallOnSlowPath);
+ return summary;
}
+class CheckStackOverflowSlowPath : public SlowPathCode {
+ public:
+ explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction)
+ : instruction_(instruction) { }
+
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Comment("CheckStackOverflowSlowPath");
+ __ Bind(entry_label());
+ compiler->SaveLiveRegisters(instruction_->locs());
+ // pending_deoptimization_env_ is needed to generate a runtime call that
+ // may throw an exception.
+ ASSERT(compiler->pending_deoptimization_env_ == NULL);
+ compiler->pending_deoptimization_env_ = instruction_->env();
+ compiler->GenerateCallRuntime(instruction_->token_pos(),
+ instruction_->deopt_id(),
+ kStackOverflowRuntimeEntry,
+ instruction_->locs());
+ compiler->pending_deoptimization_env_ = NULL;
+ compiler->RestoreLiveRegisters(instruction_->locs());
+ __ b(exit_label());
+ }
+
+ private:
+ CheckStackOverflowInstr* instruction_;
+};
+
+
void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
+ compiler->AddSlowPathCode(slow_path);
+
+ __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
+
+ __ lw(TMP, Address(TMP));
+ __ subu(TMP, SP, TMP);
+ __ blez(TMP, slow_path->entry_label());
+
+ __ Bind(slow_path->exit_label());
}
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index 24d9fd9..f76ea9d 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -379,8 +379,8 @@
class RegisterSet : public ValueObject {
public:
RegisterSet() : cpu_registers_(0), fpu_registers_(0) {
- ASSERT(kNumberOfCpuRegisters < (kWordSize * kBitsPerByte));
- ASSERT(kNumberOfFpuRegisters < (kWordSize * kBitsPerByte));
+ ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte));
+ ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte));
}
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index a9bf83d..d78a1e1 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -1030,6 +1030,13 @@
DoBranch(instr, rs_val >= 0, false);
break;
}
+ case BGEZAL: {
+ int32_t rs_val = get_register(instr->RsField());
+ // Return address is one after the delay slot.
+ set_register(RA, pc_ + (2*Instr::kInstrSize));
+ DoBranch(instr, rs_val >= 0, false);
+ break;
+ }
case BGEZL: {
// Format(instr, "bgezl 'rs, 'dest");
int32_t rs_val = get_register(instr->RsField());
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index a782ec5..9cb6525 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -5,6 +5,11 @@
#include "vm/globals.h"
#if defined(TARGET_ARCH_MIPS)
+#include "vm/assembler.h"
+#include "vm/code_generator.h"
+#include "vm/dart_entry.h"
+#include "vm/instructions.h"
+#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#define __ assembler->
@@ -66,8 +71,123 @@
}
+// Called when invoking Dart code from C++ (VM code).
+// Input parameters:
+// RA : points to return address.
+// A0 : entrypoint of the Dart function to call.
+// A1 : arguments descriptor array.
+// A2 : arguments array.
+// A3 : new context containing the current isolate pointer.
void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
- __ Unimplemented("InvokeDartCode stub");
+ // Save frame pointer coming in.
+ __ EnterStubFrame();
+
+ // Save new context and C++ ABI callee-saved registers.
+ const intptr_t kNewContextOffset =
+ -(1 + kAbiPreservedCpuRegCount) * kWordSize;
+
+ __ addiu(SP, SP, Immediate(-(3 + kAbiPreservedCpuRegCount) * kWordSize));
+ for (int i = S0; i <= S7; i++) {
+ Register r = static_cast<Register>(i);
+ __ sw(r, Address(SP, (i - S0 + 3) * kWordSize));
+ }
+ __ sw(A3, Address(SP, 2 * kWordSize));
+
+ // The new Context structure contains a pointer to the current Isolate
+ // structure. Cache the Context pointer in the CTX register so that it is
+ // available in generated code and calls to Isolate::Current() need not be
+ // done. The assumption is that this register will never be clobbered by
+ // compiled or runtime stub code.
+
+ // Cache the new Context pointer into CTX while executing Dart code.
+ __ lw(CTX, Address(A3, VMHandles::kOffsetOfRawPtrInHandle));
+
+ // Load Isolate pointer from Context structure into temporary register R8.
+ __ lw(T2, FieldAddress(CTX, Context::isolate_offset()));
+
+ // Save the top exit frame info. Use R5 as a temporary register.
+ // StackFrameIterator reads the top exit frame info saved in this frame.
+ __ lw(S5, Address(T2, Isolate::top_exit_frame_info_offset()));
+ __ LoadImmediate(T0, 0);
+ __ sw(T0, Address(T2, Isolate::top_exit_frame_info_offset()));
+
+ // Save the old Context pointer. Use S4 as a temporary register.
+ // Note that VisitObjectPointers will find this saved Context pointer during
+ // GC marking, since it traverses any information between SP and
+ // FP - kExitLinkOffsetInEntryFrame.
+ // EntryFrame::SavedContext reads the context saved in this frame.
+ __ lw(S4, Address(T2, Isolate::top_context_offset()));
+
+ // The constants kSavedContextOffsetInEntryFrame and
+ // kExitLinkOffsetInEntryFrame must be kept in sync with the code below.
+ __ sw(S5, Address(SP, 1 * kWordSize));
+ __ sw(S4, Address(SP, 0 * kWordSize));
+
+ // after the call, The stack pointer is restored to this location.
+ // Pushed A3, S0-7, S4, S5 = 11.
+ const intptr_t kSavedContextOffsetInEntryFrame = -11 * kWordSize;
+
+ // Load arguments descriptor array into S4, which is passed to Dart code.
+ __ lw(S4, Address(A1, VMHandles::kOffsetOfRawPtrInHandle));
+
+ // Load number of arguments into S5.
+ __ lw(S5, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
+ __ SmiUntag(S5);
+
+ // Compute address of 'arguments array' data area into A2.
+ __ lw(A2, Address(A2, VMHandles::kOffsetOfRawPtrInHandle));
+ __ addiu(A2, A2, Immediate(Array::data_offset() - kHeapObjectTag));
+
+ // Set up arguments for the Dart call.
+ Label push_arguments;
+ Label done_push_arguments;
+
+ __ beq(S5, ZR, &done_push_arguments); // check if there are arguments.
+ __ LoadImmediate(A1, 0);
+ __ Bind(&push_arguments);
+ __ lw(A3, Address(A2));
+ __ Push(A3);
+ __ addiu(A2, A2, Immediate(kWordSize));
+ __ addiu(A1, A1, Immediate(1));
+ __ subu(T0, A1, S5);
+ __ bltz(T0, &push_arguments);
+
+ __ Bind(&done_push_arguments);
+
+
+ // Call the Dart code entrypoint.
+ __ jalr(A0); // S4 is the arguments descriptor array.
+
+ // Read the saved new Context pointer.
+ __ lw(CTX, Address(FP, kNewContextOffset));
+ __ lw(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle));
+
+ // Get rid of arguments pushed on the stack.
+ __ addiu(SP, FP, Immediate(kSavedContextOffsetInEntryFrame));
+
+ // Load Isolate pointer from Context structure into CTX. Drop Context.
+ __ lw(CTX, FieldAddress(CTX, Context::isolate_offset()));
+
+ // Restore the saved Context pointer into the Isolate structure.
+ // Uses S4 as a temporary register for this.
+ // Restore the saved top exit frame info back into the Isolate structure.
+ // Uses S5 as a temporary register for this.
+ __ lw(S4, Address(SP, 0 * kWordSize));
+ __ lw(S5, Address(SP, 1 * kWordSize));
+ __ sw(S4, Address(CTX, Isolate::top_context_offset()));
+ __ sw(S5, Address(CTX, Isolate::top_exit_frame_info_offset()));
+
+ // Restore C++ ABI callee-saved registers.
+ for (int i = S0; i <= S7; i++) {
+ Register r = static_cast<Register>(i);
+ __ lw(r, Address(SP, (i - S0 + 3) * kWordSize));
+ }
+ __ lw(A3, Address(SP));
+ __ addiu(SP, SP, Immediate((3 + kAbiPreservedCpuRegCount) * kWordSize));
+
+ // Restore the frame pointer and return.
+ __ LeaveStubFrame();
+ __ Ret();
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
index f0552e8..5fe4cb1 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
@@ -626,7 +626,9 @@
return instructionInterval.diesAt(start);
}
- void handleInstruction(HInstruction instruction, VariableNamer namer) {
+ void freeUsedNamesAt(HInstruction instruction,
+ HInstruction at,
+ VariableNamer namer) {
// TODO(ager): We cannot perform this check to free names for
// HCheck instructions because they are special cased to have the
// same live intervals as the instruction they are checking. This
@@ -635,16 +637,26 @@
// end up checking that otherInput dies not here, but at the
// location of checkedInput. We should preserve the start id for
// the check instruction.
- if (instruction is! HCheck) {
+ if (at is HCheck) return;
+ if (needsName(instruction)) {
+ if (diesAt(instruction, at)) {
+ namer.freeName(instruction);
+ }
+ } else if (generateAtUseSite.contains(instruction)) {
+ // If the instruction is generated at use site, then all its
+ // inputs may also die at [at].
for (int i = 0, len = instruction.inputs.length; i < len; i++) {
HInstruction input = instruction.inputs[i];
- // If [input] has a name, and its use here is the last use, free
- // its name.
- if (needsName(input) && diesAt(input, instruction)) {
- namer.freeName(input);
- }
+ freeUsedNamesAt(input, at, namer);
}
}
+ }
+
+ void handleInstruction(HInstruction instruction, VariableNamer namer) {
+ for (int i = 0, len = instruction.inputs.length; i < len; i++) {
+ HInstruction input = instruction.inputs[i];
+ freeUsedNamesAt(input, instruction, namer);
+ }
if (needsName(instruction)) {
namer.allocateName(instruction);
diff --git a/tests/compiler/dart2js/ssa_phi_codegen_test.dart b/tests/compiler/dart2js/ssa_phi_codegen_test.dart
index 7cfdcc2..96c9372 100644
--- a/tests/compiler/dart2js/ssa_phi_codegen_test.dart
+++ b/tests/compiler/dart2js/ssa_phi_codegen_test.dart
@@ -55,6 +55,17 @@
}
""";
+const String TEST_FIVE = r"""
+void main() {
+ var hash = 0;
+ for (var i = 0; i == 0; i = i + 1) {
+ hash = hash + 10;
+ hash = hash + 42;
+ }
+ print(t);
+}
+""";
+
main() {
compileAndMatchFuzzy(TEST_ONE, 'foo', "var x = x === true \\? 2 : 3;");
compileAndMatchFuzzy(TEST_ONE, 'foo', "print\\(x\\);");
@@ -69,6 +80,7 @@
// only generates one instruction.
compileAndMatchFuzzy(TEST_THREE, 'foo', 'x = 42');
- var generated = compile(TEST_FOUR, entry: 'foo');
compileAndDoNotMatchFuzzy(TEST_FOUR, 'foo', '(x) = \1;');
+
+ compileAndDoNotMatch(TEST_FIVE, 'main', new RegExp('hash0'));
}
diff --git a/tests/html/html.status b/tests/html/html.status
index 0d45af0..f8c058d 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -26,6 +26,9 @@
[ $runtime == chrome ]
touchevent_test/supported: Fail
+[ $runtime == chrome && $system == windows ]
+audiocontext_test: Skip # Issue 9566
+
[$runtime == drt || $runtime == dartium || $runtime == chrome]
webgl_1_test: Pass, Fail # Issue 8219
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 9f7e85a..5ac2302 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -8,6 +8,7 @@
count_test: Fail, Crash # Bug in v8, http://dartbug.com/9407
count_stream_test: Fail, Crash # Bug in v8, http://dartbug.com/9407
mandel_isolate_test: Fail, Crash # Bug in v8, http://dartbug.com/9407
+message_test: Fail, Crash # Bug in v8, http://dartbug.com/9407
mint_maker_test: Fail, Crash # Bug in v8, http://dartbug.com/9407
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 84436a5..8ef5e6e 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -20,7 +20,7 @@
async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9002
async/run_async4_test: Pass, Fail # no global exception handler in isolates. http://dartbug.com/9012
-[ $compiler == dart2js && $runtime == chrome && $system == macos]
+[ $compiler == dart2js && $runtime == chrome && ($system == macos || $system == windows)]
crypto/hmac_sha1_test: Fail # Issue 9471
[ $compiler == dart2js && $checked ]
diff --git a/tools/VERSION b/tools/VERSION
index 217a1a6..f09938c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 4
BUILD 4
-PATCH 0
+PATCH 2
diff --git a/utils/pub/command_cache.dart b/utils/pub/command_cache.dart
index 056f383..c3a3a3d 100644
--- a/utils/pub/command_cache.dart
+++ b/utils/pub/command_cache.dart
@@ -33,18 +33,17 @@
}
// TODO(keertip): Add flag to list packages from non default sources
- return cache.sources.defaultSource.getCachedPackages().then((packages){
- var packagesObj = <String, Map>{};
- for (var package in packages){
- packagesObj[package.name] = {
- 'version': package.version.toString(),
- 'location': package.dir
- };
- }
- // TODO(keertip): Add support for non-JSON format
- // and check for --format flag
- log.message( json.stringify({'packages': packagesObj}));
- });
+ var packagesObj = <String, Map>{};
+ for (var package in cache.sources.defaultSource.getCachedPackages()) {
+ packagesObj[package.name] = {
+ 'version': package.version.toString(),
+ 'location': package.dir
+ };
+ }
+
+ // TODO(keertip): Add support for non-JSON format
+ // and check for --format flag
+ log.message(json.stringify({'packages': packagesObj}));
}
}
diff --git a/utils/pub/command_lish.dart b/utils/pub/command_lish.dart
index c2f2529..1948ba1 100644
--- a/utils/pub/command_lish.dart
+++ b/utils/pub/command_lish.dart
@@ -146,11 +146,9 @@
"--exclude-standard"]);
}
- return listDir(rootDir, recursive: true).then((entries) {
- return entries
- .where(fileExists) // Skip directories and broken symlinks.
- .map((entry) => path.relative(entry, from: rootDir));
- });
+ return listDir(rootDir, recursive: true)
+ .where(fileExists) // Skip directories and broken symlinks.
+ .map((entry) => path.relative(entry, from: rootDir));
}).then((files) => files.where(_shouldPublish).toList());
}
diff --git a/utils/pub/command_uploader.dart b/utils/pub/command_uploader.dart
index 977415b..673a4bd 100644
--- a/utils/pub/command_uploader.dart
+++ b/utils/pub/command_uploader.dart
@@ -59,7 +59,7 @@
exit(exit_codes.USAGE);
}
- return defer(() {
+ return new Future.of(() {
var package = commandOptions['package'];
if (package != null) return package;
return new Entrypoint(path.current, cache).root.name;
diff --git a/utils/pub/entrypoint.dart b/utils/pub/entrypoint.dart
index 95790d3..db6ad47 100644
--- a/utils/pub/entrypoint.dart
+++ b/utils/pub/entrypoint.dart
@@ -71,7 +71,7 @@
if (pendingOrCompleted != null) return pendingOrCompleted;
var packageDir = path.join(packagesDir, id.name);
- var future = defer(() {
+ var future = new Future.of(() {
ensureDir(path.dirname(packageDir));
if (entryExists(packageDir)) {
@@ -102,7 +102,7 @@
/// directory, respecting the [LockFile] if present. Returns a [Future] that
/// completes when all dependencies are installed.
Future installDependencies() {
- return defer(() {
+ return new Future.of(() {
return resolveVersions(cache.sources, root, loadLockFile());
}).then(_installDependencies);
}
@@ -119,7 +119,7 @@
/// other dependencies as specified by the [LockFile] if possible. Returns a
/// [Future] that completes when all dependencies are installed.
Future updateDependencies(List<String> dependencies) {
- return defer(() {
+ return new Future.of(() {
var solver = new VersionSolver(cache.sources, root, loadLockFile());
for (var dependency in dependencies) {
solver.useLatestVersion(dependency);
@@ -137,16 +137,18 @@
if (id.isRoot) return new Future.immediate(id);
return install(id);
}).toList());
- }).then(_saveLockFile)
- .then(_installSelfReference)
- .then(_linkSecondaryPackageDirs);
+ }).then((ids) {
+ _saveLockFile(ids);
+ _installSelfReference();
+ _linkSecondaryPackageDirs();
+ });
}
/// Traverses the root's package dependency graph and loads each of the
/// reached packages. This should only be called after the lockfile has been
/// successfully generated.
Future<List<Pubspec>> walkDependencies() {
- return defer(() {
+ return new Future.of(() {
var lockFile = loadLockFile();
var group = new FutureGroup<Pubspec>();
var visited = new Set<String>();
@@ -227,79 +229,59 @@
/// Installs a self-referential symlink in the `packages` directory that will
/// allow a package to import its own files using `package:`.
- Future _installSelfReference(_) {
- return defer(() {
- var linkPath = path.join(packagesDir, root.name);
- // Create the symlink if it doesn't exist.
- if (entryExists(linkPath)) return;
- ensureDir(packagesDir);
- return createPackageSymlink(root.name, root.dir, linkPath,
- isSelfLink: true, relative: true);
- });
+ void _installSelfReference() {
+ var linkPath = path.join(packagesDir, root.name);
+ // Create the symlink if it doesn't exist.
+ if (entryExists(linkPath)) return;
+ ensureDir(packagesDir);
+ createPackageSymlink(root.name, root.dir, linkPath,
+ isSelfLink: true, relative: true);
}
/// If `bin/`, `test/`, or `example/` directories exist, symlink `packages/`
/// into them so that their entrypoints can be run. Do the same for any
/// subdirectories of `test/` and `example/`.
- Future _linkSecondaryPackageDirs(_) {
+ void _linkSecondaryPackageDirs() {
var binDir = path.join(root.dir, 'bin');
var exampleDir = path.join(root.dir, 'example');
var testDir = path.join(root.dir, 'test');
var toolDir = path.join(root.dir, 'tool');
var webDir = path.join(root.dir, 'web');
- return defer(() {
- if (!dirExists(binDir)) return;
- return _linkSecondaryPackageDir(binDir);
- }).then((_) => _linkSecondaryPackageDirsRecursively(exampleDir))
- .then((_) => _linkSecondaryPackageDirsRecursively(testDir))
- .then((_) => _linkSecondaryPackageDirsRecursively(toolDir))
- .then((_) => _linkSecondaryPackageDirsRecursively(webDir));
- }
+
+ if (dirExists(binDir)) _linkSecondaryPackageDir(binDir);
+ for (var dir in ['example', 'test', 'tool', 'web']) {
+ _linkSecondaryPackageDirsRecursively(path.join(root.dir, dir));
+ }
+ }
/// Creates a symlink to the `packages` directory in [dir] and all its
/// subdirectories.
- Future _linkSecondaryPackageDirsRecursively(String dir) {
- return defer(() {
- if (!dirExists(dir)) return;
- return _linkSecondaryPackageDir(dir)
- .then((_) => _listDirWithoutPackages(dir))
- .then((files) {
- return Future.wait(files.map((file) {
- return defer(() {
- if (!dirExists(file)) return;
- return _linkSecondaryPackageDir(file);
- });
- }).toList());
- });
- });
+ void _linkSecondaryPackageDirsRecursively(String dir) {
+ if (!dirExists(dir)) return;
+ _linkSecondaryPackageDir(dir);
+ _listDirWithoutPackages(dir)
+ .where(dirExists)
+ .forEach(_linkSecondaryPackageDir);
}
// TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed.
/// Recursively lists the contents of [dir], excluding hidden `.DS_Store`
/// files and `package` files.
- Future<List<String>> _listDirWithoutPackages(dir) {
- return listDir(dir).then((files) {
- return Future.wait(files.map((file) {
- if (path.basename(file) == 'packages') return new Future.immediate([]);
- return defer(() {
- if (!dirExists(file)) return [];
- return _listDirWithoutPackages(file);
- }).then((subfiles) {
- var fileAndSubfiles = [file];
- fileAndSubfiles.addAll(subfiles);
- return fileAndSubfiles;
- });
- }).toList());
- }).then(flatten);
+ List<String> _listDirWithoutPackages(dir) {
+ return flatten(listDir(dir).map((file) {
+ if (path.basename(file) == 'packages') return [];
+ if (!dirExists(file)) return [];
+ var fileAndSubfiles = [file];
+ fileAndSubfiles.addAll(_listDirWithoutPackages(file));
+ return fileAndSubfiles;
+ }));
}
/// Creates a symlink to the `packages` directory in [dir]. Will replace one
/// if already there.
- Future _linkSecondaryPackageDir(String dir) {
- return defer(() {
- var symlink = path.join(dir, 'packages');
- if (entryExists(symlink)) deleteEntry(symlink);
- return createSymlink(packagesDir, symlink, relative: true);
- });
+ void _linkSecondaryPackageDir(String dir) {
+ var symlink = path.join(dir, 'packages');
+ if (entryExists(symlink)) deleteEntry(symlink);
+ createSymlink(packagesDir, symlink, relative: true);
}
}
diff --git a/utils/pub/error_group.dart b/utils/pub/error_group.dart
index 5e6baf8..f579d8e 100644
--- a/utils/pub/error_group.dart
+++ b/utils/pub/error_group.dart
@@ -264,7 +264,7 @@
if (_isDone) return;
_subscription.cancel();
// Call these asynchronously to work around issue 7913.
- defer(() {
+ new Future.immediate(null).then((_) {
_controller.addError(e.error, e.stackTrace);
_controller.close();
});
diff --git a/utils/pub/git_source.dart b/utils/pub/git_source.dart
index 1193892..cea2bac 100644
--- a/utils/pub/git_source.dart
+++ b/utils/pub/git_source.dart
@@ -123,7 +123,7 @@
/// future that completes once this is finished and throws an exception if it
/// fails.
Future _ensureRepoCache(PackageId id) {
- return defer(() {
+ return new Future.of(() {
var path = _repoCachePath(id);
if (!entryExists(path)) return _clone(_getUrl(id), path, mirror: true);
return git.run(["fetch"], workingDir: path).then((result) => null);
@@ -143,7 +143,7 @@
/// the working tree, but instead makes the repository a local mirror of the
/// remote repository. See the manpage for `git clone` for more information.
Future _clone(String from, String to, {bool mirror: false}) {
- return defer(() {
+ return new Future.of(() {
// Git on Windows does not seem to automatically create the destination
// directory.
ensureDir(to);
diff --git a/utils/pub/hosted_source.dart b/utils/pub/hosted_source.dart
index 4d6626f..0ed4e0c 100644
--- a/utils/pub/hosted_source.dart
+++ b/utils/pub/hosted_source.dart
@@ -63,7 +63,7 @@
/// Downloads a package from the site and unpacks it.
Future<bool> install(PackageId id, String destPath) {
- return defer(() {
+ return new Future.of(() {
var url = _makeVersionUrl(id, (server, package, version) =>
"$server/packages/$package/versions/$version.tar.gz");
log.io("Install package from $url.");
@@ -118,17 +118,13 @@
return description;
}
- Future<List<Package>> getCachedPackages() {
- return defer(() {
- var cacheDir = path.join(systemCacheRoot,
- _getSourceDirectory(_defaultUrl));
- if (!dirExists(cacheDir)) return [];
-
- return listDir(path.join(cacheDir)).then((entries) {
- return entries.map((entry) =>
- new Package.load(null, entry, systemCache.sources));
- });
- });
+ List<Package> getCachedPackages() {
+ var cacheDir = path.join(systemCacheRoot,
+ _getSourceDirectory(_defaultUrl));
+ if (!dirExists(cacheDir)) return [];
+
+ return listDir(path.join(cacheDir)).map((entry) =>
+ new Package.load(null, entry, systemCache.sources)).toList();
}
/// When an error occurs trying to read something about [package] from [url],
diff --git a/utils/pub/io.dart b/utils/pub/io.dart
index 4dcbf5d..a0e69a9 100644
--- a/utils/pub/io.dart
+++ b/utils/pub/io.dart
@@ -33,7 +33,7 @@
/// Returns whether [link] exists on the file system. This will return `true`
/// for any symlink, regardless of what it points at or whether it's broken.
-bool linkExists(String path) => new Link(path).existsSync();
+bool linkExists(String link) => new Link(link).existsSync();
/// Returns whether [file] exists on the file system. This will return `true`
/// for a symlink only if that symlink is unbroken and points to a file.
@@ -125,68 +125,55 @@
return tempDir.path;
}
-/// Asynchronously lists the contents of [dir]. If [recursive] is `true`, lists
-/// subdirectory contents (defaults to `false`). If [includeHiddenFiles] is
-/// `true`, includes files and directories beginning with `.` (defaults to
-/// `false`).
+/// Lists the contents of [dir]. If [recursive] is `true`, lists subdirectory
+/// contents (defaults to `false`). If [includeHidden] is `true`, includes files
+/// and directories beginning with `.` (defaults to `false`).
///
-/// If [dir] is a string, the returned paths are guaranteed to begin with it.
-Future<List<String>> listDir(String dir,
- {bool recursive: false, bool includeHiddenFiles: false}) {
- Future<List<String>> doList(String dir, Set<String> listedDirectories) {
+/// The returned paths are guaranteed to begin with [dir].
+List<String> listDir(String dir, {bool recursive: false,
+ bool includeHidden: false}) {
+ List<String> doList(String dir, Set<String> listedDirectories) {
var contents = <String>[];
- var completer = new Completer<List<String>>();
// Avoid recursive symlinks.
var resolvedPath = new File(dir).fullPathSync();
- if (listedDirectories.contains(resolvedPath)) {
- return new Future.immediate([]);
- }
+ if (listedDirectories.contains(resolvedPath)) return [];
listedDirectories = new Set<String>.from(listedDirectories);
listedDirectories.add(resolvedPath);
log.io("Listing directory $dir.");
- var lister = new Directory(dir).list();
var children = [];
- lister.listen(
- (entity) {
- if (entity is File) {
- var file = entity.path;
- if (!includeHiddenFiles && path.basename(file).startsWith('.')) {
- return;
- }
- contents.add(file);
- } else if (entity is Directory) {
- var file = entity.path;
- if (!includeHiddenFiles && path.basename(file).startsWith('.')) {
- return;
- }
- contents.add(file);
- // TODO(nweiz): don't manually recurse once issue 4794 is fixed.
- // Note that once we remove the manual recursion, we'll need to
- // explicitly filter out files in hidden directories.
- if (recursive) {
- children.add(doList(file, listedDirectories));
- }
- }
- },
- onDone: () {
- // TODO(rnystrom): May need to sort here if it turns out
- // onDir and onFile aren't guaranteed to be called in a
- // certain order. So far, they seem to.
- log.fine("Listed directory $dir:\n${contents.join('\n')}");
- completer.complete(contents);
- },
- onError: (error) => completer.completeError(error));
+ for (var entity in new Directory(dir).listSync(followLinks: false)) {
+ var entityPath = entity.path;
+ if (!includeHidden && path.basename(entityPath).startsWith('.')) continue;
- return completer.future.then((contents) {
- return Future.wait(children).then((childContents) {
- contents.addAll(flatten(childContents));
- return contents;
- });
- });
+ // TODO(nweiz): remove this when issue 4928 is fixed.
+ if (entity is Link) {
+ // We treat broken symlinks as files, in that we don't want to recurse
+ // into them.
+ entity = dirExists(entityPath)
+ ? new Directory(entityPath)
+ : new File(entityPath);
+ }
+
+ if (entity is File) {
+ contents.add(entityPath);
+ } else if (entity is Directory) {
+ contents.add(entityPath);
+ // TODO(nweiz): don't manually recurse once issue 4794 is fixed.
+ // Note that once we remove the manual recursion, we'll need to
+ // explicitly filter out files in hidden directories.
+ if (recursive) {
+ children.addAll(doList(entityPath, listedDirectories));
+ }
+ }
+ }
+
+ log.fine("Listed directory $dir:\n${contents.join('\n')}");
+ contents.addAll(children);
+ return contents;
}
return doList(dir, new Set<String>());
@@ -210,7 +197,7 @@
} else if (dirExists(path)) {
log.io("Deleting directory $path.");
new Directory(path).deleteSync(recursive: true);
- } else {
+ } else if (fileExists(path)) {
log.io("Deleting file $path.");
new File(path).deleteSync();
}
@@ -236,7 +223,7 @@
/// symlink to the target. Otherwise, uses the [target] path unmodified.
///
/// Note that on Windows, only directories may be symlinked to.
-Future<String> createSymlink(String target, String symlink,
+void createSymlink(String target, String symlink,
{bool relative: false}) {
if (relative) {
// Relative junction points are not supported on Windows. Instead, just
@@ -252,51 +239,32 @@
}
log.fine("Creating $symlink pointing to $target");
-
- var command = 'ln';
- var args = ['-s', target, symlink];
-
- if (Platform.operatingSystem == 'windows') {
- // Call mklink on Windows to create an NTFS junction point. Only works on
- // Vista or later. (Junction points are available earlier, but the "mklink"
- // command is not.) I'm using a junction point (/j) here instead of a soft
- // link (/d) because the latter requires some privilege shenanigans that
- // I'm not sure how to specify from the command line.
- command = 'mklink';
- args = ['/j', symlink, target];
- }
-
- // TODO(rnystrom): Check exit code and output?
- return runProcess(command, args).then((result) => symlink);
+ new Link(symlink).createSync(target);
}
/// Creates a new symlink that creates an alias at [symlink] that points to the
-/// `lib` directory of package [target]. Returns a [Future] which completes to
-/// the path to the symlink file. If [target] does not have a `lib` directory,
-/// this shows a warning if appropriate and then does nothing.
+/// `lib` directory of package [target]. If [target] does not have a `lib`
+/// directory, this shows a warning if appropriate and then does nothing.
///
/// If [relative] is true, creates a symlink with a relative path from the
/// symlink to the target. Otherwise, uses the [target] path unmodified.
-Future<String> createPackageSymlink(String name, String target, String symlink,
+void createPackageSymlink(String name, String target, String symlink,
{bool isSelfLink: false, bool relative: false}) {
- return defer(() {
- // See if the package has a "lib" directory.
- target = path.join(target, 'lib');
- log.fine("Creating ${isSelfLink ? "self" : ""}link for package '$name'.");
- if (dirExists(target)) {
- return createSymlink(target, symlink, relative: relative);
- }
+ // See if the package has a "lib" directory.
+ target = path.join(target, 'lib');
+ log.fine("Creating ${isSelfLink ? "self" : ""}link for package '$name'.");
+ if (dirExists(target)) {
+ createSymlink(target, symlink, relative: relative);
+ return;
+ }
- // It's OK for the self link (i.e. the root package) to not have a lib
- // directory since it may just be a leaf application that only has
- // code in bin or web.
- if (!isSelfLink) {
- log.warning('Warning: Package "$name" does not have a "lib" directory so '
- 'you will not be able to import any libraries from it.');
- }
-
- return symlink;
- });
+ // It's OK for the self link (i.e. the root package) to not have a lib
+ // directory since it may just be a leaf application that only has
+ // code in bin or web.
+ if (!isSelfLink) {
+ log.warning('Warning: Package "$name" does not have a "lib" directory so '
+ 'you will not be able to import any libraries from it.');
+ }
}
/// Resolves [target] relative to the location of pub.dart.
@@ -585,7 +553,7 @@
/// Returns a future that completes to the value that the future returned from
/// [fn] completes to.
Future withTempDir(Future fn(String path)) {
- return defer(() {
+ return new Future.of(() {
var tempDir = createTempDir();
return new Future.of(() => fn(tempDir))
.whenComplete(() => deleteEntry(tempDir));
@@ -651,18 +619,13 @@
'${result.stdout.join("\n")}\n'
'${result.stderr.join("\n")}';
}
- // Find the tar file we just created since we don't know its name.
- return listDir(tempDir);
- }).then((files) {
- var tarFile;
- for (var file in files) {
- if (path.extension(file) == '.tar') {
- tarFile = file;
- break;
- }
- }
- if (tarFile == null) throw 'The gzip file did not contain a tar file.';
+ // Find the tar file we just created since we don't know its name.
+ var tarFile = listDir(tempDir).firstWhere(
+ (file) => path.extension(file) == '.tar',
+ orElse: () {
+ throw 'The gzip file did not contain a tar file.';
+ });
// Untar the archive into the destination directory.
return runProcess(command, ['x', tarFile], workingDir: destination);
diff --git a/utils/pub/oauth2.dart b/utils/pub/oauth2.dart
index ced3ed4..85bfed7 100644
--- a/utils/pub/oauth2.dart
+++ b/utils/pub/oauth2.dart
@@ -104,7 +104,7 @@
/// Gets a new OAuth2 client. If saved credentials are available, those are
/// used; otherwise, the user is prompted to authorize the pub client.
Future<Client> _getClient(SystemCache cache) {
- return defer(() {
+ return new Future.of(() {
var credentials = _loadCredentials(cache);
if (credentials == null) return _authorize();
diff --git a/utils/pub/package.dart b/utils/pub/package.dart
index 1bc7445..d3d9819 100644
--- a/utils/pub/package.dart
+++ b/utils/pub/package.dart
@@ -43,20 +43,18 @@
/// same conventions as pub.dartlang.org for choosing the primary one: the
/// README with the fewest extensions that is lexically ordered first is
/// chosen.
- Future<String> get readmePath {
- return listDir(dir).then((entries) {
- var readmes = entries.map(path.basename).
- where((entry) => entry.contains(_README_REGEXP));
- if (readmes.isEmpty) return;
+ String get readmePath {
+ var readmes = listDir(dir).map(path.basename).
+ where((entry) => entry.contains(_README_REGEXP));
+ if (readmes.isEmpty) return;
- return path.join(dir, readmes.min((readme1, readme2) {
- var extensions1 = ".".allMatches(readme1).length;
- var extensions2 = ".".allMatches(readme2).length;
- var comparison = extensions1.compareTo(extensions2);
- if (comparison != 0) return comparison;
- return readme1.compareTo(readme2);
- }));
- });
+ return path.join(dir, readmes.min((readme1, readme2) {
+ var extensions1 = ".".allMatches(readme1).length;
+ var extensions2 = ".".allMatches(readme2).length;
+ var comparison = extensions1.compareTo(extensions2);
+ if (comparison != 0) return comparison;
+ return readme1.compareTo(readme2);
+ }));
}
/// Loads the package whose root directory is [packageDir]. [name] is the
diff --git a/utils/pub/path_source.dart b/utils/pub/path_source.dart
index 3b433a1..e849b6f 100644
--- a/utils/pub/path_source.dart
+++ b/utils/pub/path_source.dart
@@ -25,7 +25,7 @@
final shouldCache = false;
Future<Pubspec> describe(PackageId id) {
- return defer(() {
+ return new Future.of(() {
_validatePath(id.name, id.description);
return new Pubspec.load(id.name, id.description["path"],
systemCache.sources);
@@ -40,16 +40,17 @@
}
Future<bool> install(PackageId id, String destination) {
- return defer(() {
+ return new Future.of(() {
try {
_validatePath(id.name, id.description);
} on FormatException catch(err) {
return false;
}
- return createPackageSymlink(id.name, id.description["path"], destination,
+ createPackageSymlink(id.name, id.description["path"], destination,
relative: id.description["relative"]);
- }).then((_) => true);
+ return true;
+ });
}
/// Parses a path dependency. This takes in a path string and returns a map.
diff --git a/utils/pub/pub.dart b/utils/pub/pub.dart
index 5f52a53..811c198 100644
--- a/utils/pub/pub.dart
+++ b/utils/pub/pub.dart
@@ -145,7 +145,7 @@
/// Checks that pub is running on a supported platform. If it isn't, it prints
/// an error message and exits. Completes when the validation is done.
Future validatePlatform() {
- return defer(() {
+ return new Future.of(() {
if (Platform.operatingSystem != 'windows') return;
return runProcess('ver', []).then((result) {
@@ -265,7 +265,7 @@
exit(_chooseExitCode(error));
}
- defer(() {
+ new Future.of(() {
if (requiresEntrypoint) {
// TODO(rnystrom): Will eventually need better logic to walk up
// subdirectories until we hit one that looks package-like. For now,
diff --git a/utils/pub/source.dart b/utils/pub/source.dart
index 109b5b2..adb9571 100644
--- a/utils/pub/source.dart
+++ b/utils/pub/source.dart
@@ -113,17 +113,12 @@
packageDir = p;
// See if it's already cached.
- if (!dirExists(packageDir)) return false;
-
- return _isCachedPackageCorrupted(packageDir).then((isCorrupted) {
- if (!isCorrupted) return true;
-
+ if (dirExists(packageDir)) {
+ if (!_isCachedPackageCorrupted(packageDir)) return true;
// Busted, so wipe out the package and reinstall.
deleteEntry(packageDir);
- return false;
- });
- }).then((isInstalled) {
- if (isInstalled) return true;
+ }
+
ensureDir(path.dirname(packageDir));
return install(id, packageDir);
}).then((found) {
@@ -143,18 +138,14 @@
///
/// * It has an empty "lib" directory.
/// * It has no pubspec.
- Future<bool> _isCachedPackageCorrupted(String packageDir) {
- return defer(() {
- if (!fileExists(path.join(packageDir, "pubspec.yaml"))) return true;
+ bool _isCachedPackageCorrupted(String packageDir) {
+ if (!fileExists(path.join(packageDir, "pubspec.yaml"))) return true;
- var libDir = path.join(packageDir, "lib");
- if (dirExists(libDir)) {
- return listDir(libDir).then((contents) => contents.length == 0);
- }
+ var libDir = path.join(packageDir, "lib");
+ if (dirExists(libDir)) return listDir(libDir).length == 0;
- // If we got here, it's OK.
- return false;
- });
+ // If we got here, it's OK.
+ return false;
}
/// Returns the directory in the system cache that the package identified by
@@ -218,7 +209,7 @@
Future<PackageId> resolveId(PackageId id) => new Future.immediate(id);
/// Returns the [Package]s that have been installed in the system cache.
- Future<List<Package>> getCachedPackages() {
+ List<Package> getCachedPackages() {
if (shouldCache) throw "Source $name must implement this.";
}
diff --git a/utils/pub/utils.dart b/utils/pub/utils.dart
index d354e68..cb316cbe 100644
--- a/utils/pub/utils.dart
+++ b/utils/pub/utils.dart
@@ -145,16 +145,6 @@
return CryptoUtils.bytesToHex(sha.close());
}
-/// Invokes the given callback asynchronously. Returns a [Future] that completes
-/// to the result of [callback].
-///
-/// This is also used to wrap synchronous code that may thrown an exception to
-/// ensure that methods that have both sync and async code only report errors
-/// asynchronously.
-Future defer(callback()) {
- return new Future.immediate(null).then((_) => callback());
-}
-
/// Returns a [Future] that completes in [milliseconds].
Future sleep(int milliseconds) {
var completer = new Completer();
diff --git a/utils/pub/validator/compiled_dartdoc.dart b/utils/pub/validator/compiled_dartdoc.dart
index b139869..1998c47 100644
--- a/utils/pub/validator/compiled_dartdoc.dart
+++ b/utils/pub/validator/compiled_dartdoc.dart
@@ -20,8 +20,8 @@
: super(entrypoint);
Future validate() {
- return listDir(entrypoint.root.dir, recursive: true).then((entries) {
- for (var entry in entries) {
+ return new Future.of(() {
+ for (var entry in listDir(entrypoint.root.dir, recursive: true)) {
if (path.basename(entry) != "nav.json") continue;
var dir = path.dirname(entry);
diff --git a/utils/pub/validator/directory.dart b/utils/pub/validator/directory.dart
index 032c0d1..5d6628d 100644
--- a/utils/pub/validator/directory.dart
+++ b/utils/pub/validator/directory.dart
@@ -21,8 +21,8 @@
static final _PLURAL_NAMES = ["tools", "tests", "docs", "examples"];
Future validate() {
- return listDir(entrypoint.root.dir).then((dirs) {
- for (var dir in dirs) {
+ return new Future.of(() {
+ for (var dir in listDir(entrypoint.root.dir)) {
if (!dirExists(dir)) continue;
dir = path.basename(dir);
diff --git a/utils/pub/validator/lib.dart b/utils/pub/validator/lib.dart
index c31b071..7ff06fc 100644
--- a/utils/pub/validator/lib.dart
+++ b/utils/pub/validator/lib.dart
@@ -23,26 +23,26 @@
: super(entrypoint);
Future validate() {
- var libDir = path.join(entrypoint.root.dir, "lib");
+ return new Future.of(() {
+ var libDir = path.join(entrypoint.root.dir, "lib");
- return defer(() {
if (!dirExists(libDir)) {
errors.add('You must have a "lib" directory.\n'
"Without that, users cannot import any code from your package.");
return;
}
- return listDir(libDir).then((files) {
- files = files.map((file) => path.relative(file, from: libDir)).toList();
- if (files.isEmpty) {
- errors.add('You must have a non-empty "lib" directory.\n'
- "Without that, users cannot import any code from your package.");
- } else if (files.length == 1 && files.first == "src") {
- errors.add('The "lib" directory must contain something other than '
- '"src".\n'
- "Otherwise, users cannot import any code from your package.");
- }
- });
+ var files = listDir(libDir)
+ .map((file) => path.relative(file, from: libDir))
+ .toList();
+ if (files.isEmpty) {
+ errors.add('You must have a non-empty "lib" directory.\n'
+ "Without that, users cannot import any code from your package.");
+ } else if (files.length == 1 && files.first == "src") {
+ errors.add('The "lib" directory must contain something other than '
+ '"src".\n'
+ "Otherwise, users cannot import any code from your package.");
+ }
});
}
}
diff --git a/utils/pub/validator/license.dart b/utils/pub/validator/license.dart
index 6cd623b..ffcbd10 100644
--- a/utils/pub/validator/license.dart
+++ b/utils/pub/validator/license.dart
@@ -19,10 +19,14 @@
: super(entrypoint);
Future validate() {
- return listDir(entrypoint.root.dir).then((files) {
+ return new Future.of(() {
var licenseLike = new RegExp(
r"^([a-zA-Z0-9]+[-_])?(LICENSE|COPYING)(\..*)?$");
- if (files.map(path.basename).any(licenseLike.hasMatch)) return;
+ if (listDir(entrypoint.root.dir)
+ .map(path.basename)
+ .any(licenseLike.hasMatch)) {
+ return;
+ }
errors.add(
"You must have a COPYING or LICENSE file in the root directory.\n"
diff --git a/utils/pub/validator/name.dart b/utils/pub/validator/name.dart
index 2dc93e5..412d6c3 100644
--- a/utils/pub/validator/name.dart
+++ b/utils/pub/validator/name.dart
@@ -28,10 +28,11 @@
: super(entrypoint);
Future validate() {
- _checkName(entrypoint.root.name, 'Package name "${entrypoint.root.name}"',
- isPackage: true);
+ return new Future.of(() {
+ _checkName(entrypoint.root.name, 'Package name "${entrypoint.root.name}"',
+ isPackage: true);
- return _libraries.then((libraries) {
+ var libraries = _libraries;
for (var library in libraries) {
var libName = path.basenameWithoutExtension(library);
_checkName(libName, 'The name of "$library", "$libName",',
@@ -50,18 +51,14 @@
/// Returns a list of all libraries in the current package as paths relative
/// to the package's root directory.
- Future<List<String>> get _libraries {
+ List<String> get _libraries {
var libDir = path.join(entrypoint.root.dir, "lib");
- return defer(() {
- if (!dirExists(libDir)) return [];
- return listDir(libDir, recursive: true);
- }).then((files) {
- return files
- .map((file) => path.relative(file, from: path.dirname(libDir)))
- .where((file) => !path.split(file).contains("src") &&
- path.extension(file) == '.dart')
- .toList();
- });
+ if (!dirExists(libDir)) return [];
+ return listDir(libDir, recursive: true)
+ .map((file) => path.relative(file, from: path.dirname(libDir)))
+ .where((file) => !path.split(file).contains("src") &&
+ path.extension(file) == '.dart')
+ .toList();
}
void _checkName(String name, String description, {bool isPackage}) {
diff --git a/utils/pub/validator/utf8_readme.dart b/utils/pub/validator/utf8_readme.dart
index 145ac86..8bf52a9 100644
--- a/utils/pub/validator/utf8_readme.dart
+++ b/utils/pub/validator/utf8_readme.dart
@@ -20,7 +20,8 @@
: super(entrypoint);
Future validate() {
- return entrypoint.root.readmePath.then((readme) {
+ return new Future.of(() {
+ var readme = entrypoint.root.readmePath;
if (readme == null) return;
var bytes = readBinaryFile(readme);
try {
diff --git a/utils/tests/pub/descriptor/tar.dart b/utils/tests/pub/descriptor/tar.dart
index 18af2b3..453793d 100644
--- a/utils/tests/pub/descriptor/tar.dart
+++ b/utils/tests/pub/descriptor/tar.dart
@@ -27,8 +27,9 @@
return Future.wait(contents.map((entry) {
return entry.create(tempDir);
})).then((_) {
- return listDir(tempDir, recursive: true, includeHiddenFiles: true);
- }).then((createdContents) {
+ var createdContents = listDir(tempDir,
+ recursive: true,
+ includeHidden: true);
return createTarGz(createdContents, baseDir: tempDir).toBytes();
}).then((bytes) {
var file = path.join(parent, name);
diff --git a/utils/tests/pub/io_test.dart b/utils/tests/pub/io_test.dart
index 585d068..54e165f 100644
--- a/utils/tests/pub/io_test.dart
+++ b/utils/tests/pub/io_test.dart
@@ -19,120 +19,118 @@
group('listDir', () {
test('lists a simple directory non-recursively', () {
expect(withTempDir((temp) {
- var future = defer(() {
- writeTextFile(path.join(temp, 'file1.txt'), '');
- writeTextFile(path.join(temp, 'file2.txt'), '');
- createDir(path.join(temp, 'subdir'));
- writeTextFile(path.join(temp, 'subdir', 'file3.txt'), '');
- return listDir(temp);
- });
- expect(future, completion(unorderedEquals([
+ writeTextFile(path.join(temp, 'file1.txt'), '');
+ writeTextFile(path.join(temp, 'file2.txt'), '');
+ createDir(path.join(temp, 'subdir'));
+ writeTextFile(path.join(temp, 'subdir', 'file3.txt'), '');
+
+ expect(listDir(temp), unorderedEquals([
path.join(temp, 'file1.txt'),
path.join(temp, 'file2.txt'),
path.join(temp, 'subdir')
- ])));
- return future;
+ ]));
}), completes);
});
test('lists a simple directory recursively', () {
expect(withTempDir((temp) {
- var future = defer(() {
- writeTextFile(path.join(temp, 'file1.txt'), '');
- writeTextFile(path.join(temp, 'file2.txt'), '');
- createDir(path.join(temp, 'subdir'));
- writeTextFile(path.join(temp, 'subdir', 'file3.txt'), '');
- return listDir(temp, recursive: true);
- });
+ writeTextFile(path.join(temp, 'file1.txt'), '');
+ writeTextFile(path.join(temp, 'file2.txt'), '');
+ createDir(path.join(temp, 'subdir'));
+ writeTextFile(path.join(temp, 'subdir', 'file3.txt'), '');
- expect(future, completion(unorderedEquals([
+ expect(listDir(temp, recursive: true), unorderedEquals([
path.join(temp, 'file1.txt'),
path.join(temp, 'file2.txt'),
path.join(temp, 'subdir'),
path.join(temp, 'subdir', 'file3.txt'),
- ])));
- return future;
+ ]));
}), completes);
});
test('ignores hidden files by default', () {
expect(withTempDir((temp) {
- var future = defer(() {
- writeTextFile(path.join(temp, 'file1.txt'), '');
- writeTextFile(path.join(temp, 'file2.txt'), '');
- writeTextFile(path.join(temp, '.file3.txt'), '');
- createDir(path.join(temp, '.subdir'));
- writeTextFile(path.join(temp, '.subdir', 'file3.txt'), '');
- return listDir(temp, recursive: true);
- });
- expect(future, completion(unorderedEquals([
+ writeTextFile(path.join(temp, 'file1.txt'), '');
+ writeTextFile(path.join(temp, 'file2.txt'), '');
+ writeTextFile(path.join(temp, '.file3.txt'), '');
+ createDir(path.join(temp, '.subdir'));
+ writeTextFile(path.join(temp, '.subdir', 'file3.txt'), '');
+
+ expect(listDir(temp, recursive: true), unorderedEquals([
path.join(temp, 'file1.txt'),
path.join(temp, 'file2.txt')
- ])));
- return future;
+ ]));
}), completes);
});
test('includes hidden files when told to', () {
expect(withTempDir((temp) {
- var future = defer(() {
- writeTextFile(path.join(temp, 'file1.txt'), '');
- writeTextFile(path.join(temp, 'file2.txt'), '');
- writeTextFile(path.join(temp, '.file3.txt'), '');
- createDir(path.join(temp, '.subdir'));
- writeTextFile(path.join(temp, '.subdir', 'file3.txt'), '');
- return listDir(temp, recursive: true, includeHiddenFiles: true);
- });
- expect(future, completion(unorderedEquals([
+ writeTextFile(path.join(temp, 'file1.txt'), '');
+ writeTextFile(path.join(temp, 'file2.txt'), '');
+ writeTextFile(path.join(temp, '.file3.txt'), '');
+ createDir(path.join(temp, '.subdir'));
+ writeTextFile(path.join(temp, '.subdir', 'file3.txt'), '');
+
+ expect(listDir(temp, recursive: true, includeHidden: true),
+ unorderedEquals([
path.join(temp, 'file1.txt'),
path.join(temp, 'file2.txt'),
path.join(temp, '.file3.txt'),
path.join(temp, '.subdir'),
path.join(temp, '.subdir', 'file3.txt')
- ])));
- return future;
+ ]));
}), completes);
});
test('returns the unresolved paths for symlinks', () {
expect(withTempDir((temp) {
var dirToList = path.join(temp, 'dir-to-list');
- var future = defer(() {
- createDir(path.join(temp, 'dir1'));
- writeTextFile(path.join(temp, 'dir1', 'file1.txt'), '');
- createDir(path.join(temp, 'dir2'));
- writeTextFile(path.join(temp, 'dir2', 'file2.txt'), '');
- createDir(dirToList);
- return createSymlink(path.join(temp, 'dir1'),
- path.join(dirToList, 'linked-dir1'));
- }).then((_) {
- createDir(path.join(dirToList, 'subdir'));
- return createSymlink(
- path.join(temp, 'dir2'),
- path.join(dirToList, 'subdir', 'linked-dir2'));
- }).then((_) => listDir(dirToList, recursive: true));
- expect(future, completion(unorderedEquals([
+ createDir(path.join(temp, 'dir1'));
+ writeTextFile(path.join(temp, 'dir1', 'file1.txt'), '');
+ createDir(path.join(temp, 'dir2'));
+ writeTextFile(path.join(temp, 'dir2', 'file2.txt'), '');
+ createDir(dirToList);
+ createSymlink(
+ path.join(temp, 'dir1'),
+ path.join(dirToList, 'linked-dir1'));
+ createDir(path.join(dirToList, 'subdir'));
+ createSymlink(
+ path.join(temp, 'dir2'),
+ path.join(dirToList, 'subdir', 'linked-dir2'));
+
+ expect(listDir(dirToList, recursive: true), unorderedEquals([
path.join(dirToList, 'linked-dir1'),
path.join(dirToList, 'linked-dir1', 'file1.txt'),
path.join(dirToList, 'subdir'),
path.join(dirToList, 'subdir', 'linked-dir2'),
path.join(dirToList, 'subdir', 'linked-dir2', 'file2.txt'),
- ])));
- return future;
+ ]));
}), completes);
});
test('works with recursive symlinks', () {
expect(withTempDir((temp) {
- var future = defer(() {
- writeTextFile(path.join(temp, 'file1.txt'), '');
- return createSymlink(temp, path.join(temp, 'linkdir'));
- }).then((_) => listDir(temp, recursive: true));
- expect(future, completion(unorderedEquals([
+ writeTextFile(path.join(temp, 'file1.txt'), '');
+ createSymlink(temp, path.join(temp, 'linkdir'));
+
+ expect(listDir(temp, recursive: true), unorderedEquals([
path.join(temp, 'file1.txt'),
path.join(temp, 'linkdir')
- ])));
- return future;
+ ]));
+ }), completes);
+ });
+
+ test('treats a broken symlink as a file', () {
+ expect(withTempDir((temp) {
+ writeTextFile(path.join(temp, 'file1.txt'), '');
+ createDir(path.join(temp, 'dir'));
+ createSymlink(path.join(temp, 'dir'), path.join(temp, 'linkdir'));
+ deleteEntry(path.join(temp, 'dir'));
+
+ expect(listDir(temp, recursive: true), unorderedEquals([
+ path.join(temp, 'file1.txt'),
+ path.join(temp, 'linkdir')
+ ]));
}), completes);
});
});
@@ -190,17 +188,17 @@
group(name, () {
test('returns $forFile for a file', () {
expect(withTempDir((temp) {
- var path = path.join(temp, "test.txt");
- writeTextFile(path, "contents");
- expect(predicate(path), equals(forFile));
+ var file = path.join(temp, "test.txt");
+ writeTextFile(file, "contents");
+ expect(predicate(file), equals(forFile));
}), completes);
});
test('returns $forDirectory for a directory', () {
expect(withTempDir((temp) {
- var path = path.join(temp, "dir");
- createDir(path);
- expect(predicate(path), equals(forDirectory));
+ var file = path.join(temp, "dir");
+ createDir(file);
+ expect(predicate(file), equals(forDirectory));
}), completes);
});
@@ -209,9 +207,8 @@
var targetPath = path.join(temp, "dir");
var symlinkPath = path.join(temp, "linkdir");
createDir(targetPath);
- return createSymlink(targetPath, symlinkPath).then((_) {
- expect(predicate(symlinkPath), equals(forDirectorySymlink));
- });
+ createSymlink(targetPath, symlinkPath);
+ expect(predicate(symlinkPath), equals(forDirectorySymlink));
}), completes);
});
@@ -222,12 +219,10 @@
var symlink1Path = path.join(temp, "link1dir");
var symlink2Path = path.join(temp, "link2dir");
createDir(targetPath);
- return createSymlink(targetPath, symlink1Path)
- .then((_) => createSymlink(symlink1Path, symlink2Path))
- .then((_) {
- expect(predicate(symlink2Path),
+ createSymlink(targetPath, symlink1Path);
+ createSymlink(symlink1Path, symlink2Path);
+ expect(predicate(symlink2Path),
equals(forMultiLevelDirectorySymlink));
- });
}), completes);
});
@@ -236,10 +231,9 @@
var targetPath = path.join(temp, "dir");
var symlinkPath = path.join(temp, "linkdir");
createDir(targetPath);
- return createSymlink(targetPath, symlinkPath).then((_) {
- deleteEntry(targetPath);
- expect(predicate(symlinkPath), equals(forBrokenSymlink));
- });
+ createSymlink(targetPath, symlinkPath);
+ deleteEntry(targetPath);
+ expect(predicate(symlinkPath), equals(forBrokenSymlink));
}), completes);
});
@@ -250,12 +244,10 @@
var symlink1Path = path.join(temp, "link1dir");
var symlink2Path = path.join(temp, "link2dir");
createDir(targetPath);
- return createSymlink(targetPath, symlink1Path)
- .then((_) => createSymlink(symlink1Path, symlink2Path))
- .then((_) {
- deleteEntry(targetPath);
- expect(predicate(symlink2Path), equals(forMultiLevelBrokenSymlink));
- });
+ createSymlink(targetPath, symlink1Path);
+ createSymlink(symlink1Path, symlink2Path);
+ deleteEntry(targetPath);
+ expect(predicate(symlink2Path), equals(forMultiLevelBrokenSymlink));
}), completes);
});
@@ -266,9 +258,8 @@
var targetPath = path.join(temp, "test.txt");
var symlinkPath = path.join(temp, "link.txt");
writeTextFile(targetPath, "contents");
- return createSymlink(targetPath, symlinkPath).then((_) {
- expect(predicate(symlinkPath), equals(forFileSymlink));
- });
+ createSymlink(targetPath, symlinkPath);
+ expect(predicate(symlinkPath), equals(forFileSymlink));
}), completes);
});
@@ -279,11 +270,9 @@
var symlink1Path = path.join(temp, "link1.txt");
var symlink2Path = path.join(temp, "link2.txt");
writeTextFile(targetPath, "contents");
- return createSymlink(targetPath, symlink1Path)
- .then((_) => createSymlink(symlink1Path, symlink2Path))
- .then((_) {
- expect(predicate(symlink2Path), equals(forMultiLevelFileSymlink));
- });
+ createSymlink(targetPath, symlink1Path);
+ createSymlink(symlink1Path, symlink2Path);
+ expect(predicate(symlink2Path), equals(forMultiLevelFileSymlink));
}), completes);
});
}
diff --git a/utils/tests/pub/test_pub.dart b/utils/tests/pub/test_pub.dart
index 156f616..e2dc335 100644
--- a/utils/tests/pub/test_pub.dart
+++ b/utils/tests/pub/test_pub.dart
@@ -45,11 +45,15 @@
/// test configuration for the machine running the tests.
initConfig() {
// If we aren't running on the bots, use the human-friendly config.
- if (new Options().arguments.contains('--human')) {
- configure(new CommandLineConfiguration());
+ if (!runningOnBuildbot) {
+ unittestConfiguration = new CommandLineConfiguration();
}
}
+/// Returns whether we're running on a Dart build bot.
+bool get runningOnBuildbot =>
+ Platform.environment.containsKey('BUILDBOT_BUILDERNAME');
+
/// The current [HttpServer] created using [serve].
var _server;
@@ -212,10 +216,6 @@
/// Set to true when the current batch of scheduled events should be aborted.
bool _abortScheduled = false;
-/// The time (in milliseconds) to wait for the entire scheduled test to
-/// complete.
-final _TIMEOUT = 30000;
-
/// Defines an integration test. The [body] should schedule a series of
/// operations which will be run asynchronously.
void integration(String description, void body()) =>
@@ -227,6 +227,11 @@
void _integration(String description, void body(), [Function testFn]) {
testFn(description, () {
+ // The windows bots are very slow, so we increase the default timeout.
+ if (Platform.operatingSystem == "windows") {
+ currentSchedule.timeout = new Duration(seconds: 10);
+ }
+
// Ensure the SDK version is always available.
d.dir(sdkPath, [
d.file('version', '0.1.2.3')
@@ -398,7 +403,7 @@
schedule(() {
return gitlib.isInstalled.then((installed) {
if (installed) return;
- if (Platform.environment.containsKey('BUILDBOT_BUILDERNAME')) return;
+ if (runningOnBuildbot) return;
currentSchedule.abort();
});
}, 'ensuring that Git is installed');
@@ -578,7 +583,7 @@
return schedule(() {
var cache = new SystemCache.withSources(path.join(sandboxDir, cachePath));
- return defer(() {
+ return new Future.of(() {
var validator = fn(new Entrypoint(path.join(sandboxDir, appPath), cache));
return validator.validate().then((_) {
return new Pair(validator.errors, validator.warnings);
diff --git a/utils/tests/pub/version_solver_test.dart b/utils/tests/pub/version_solver_test.dart
index 835139a3..94a7c58 100644
--- a/utils/tests/pub/version_solver_test.dart
+++ b/utils/tests/pub/version_solver_test.dart
@@ -481,13 +481,11 @@
: _packages = <String, Map<Version, Package>>{};
Future<List<Version>> getVersions(String name, String description) {
- return defer(() => _packages[description].keys.toList());
+ return new Future.of(() => _packages[description].keys.toList());
}
Future<Pubspec> describe(PackageId id) {
- return defer(() {
- return _packages[id.name][id.version].pubspec;
- });
+ return new Future.of(() => _packages[id.name][id.version].pubspec);
}
Future<bool> install(PackageId id, String path) {