diff --git a/lib/src/command/global_run.dart b/lib/src/command/global_run.dart index 7fc07a7aa5792794506057705746ac7e8bb946c2..ce0085cbfd9dbcf030c2a0bfa1edc4c5a0b1bfaf 100644 --- a/lib/src/command/global_run.dart +++ b/lib/src/command/global_run.dart @@ -26,6 +26,8 @@ class GlobalRunCommand extends PubCommand { BarbackMode get mode => new BarbackMode(argResults["mode"]); GlobalRunCommand() { + argParser.addFlag("checked", abbr: "c", + help: "Enable runtime type checks and assertions."); argParser.addOption("mode", defaultsTo: "release", help: 'Mode to run transformers in.'); } @@ -48,14 +50,12 @@ class GlobalRunCommand extends PubCommand { var args = argResults.rest.skip(1).toList(); if (p.split(executable).length > 1) { - // TODO(nweiz): Use adjacent strings when the new async/await compiler - // lands. - usageException('Cannot run an executable in a subdirectory of a global ' + + usageException('Cannot run an executable in a subdirectory of a global ' 'package.'); } var exitCode = await globals.runExecutable(package, executable, args, - mode: mode); + checked: argResults["checked"], mode: mode); await flushThenExit(exitCode); } } diff --git a/lib/src/command/run.dart b/lib/src/command/run.dart index ad82c7df42c5747494e909e3da32f8138dac8e70..9e60c8162b4a174b04692d80a5d6bb28d957e99d 100644 --- a/lib/src/command/run.dart +++ b/lib/src/command/run.dart @@ -22,6 +22,8 @@ class RunCommand extends PubCommand { bool get allowTrailingOptions => false; RunCommand() { + argParser.addFlag("checked", abbr: "c", + help: "Enable runtime type checks and assertions."); argParser.addOption("mode", help: 'Mode to run transformers in.\n' '(defaults to "release" for dependencies, "debug" for ' @@ -66,7 +68,7 @@ class RunCommand extends PubCommand { } var exitCode = await runExecutable(entrypoint, package, executable, args, - mode: mode); + checked: argResults['checked'], mode: mode); await flushThenExit(exitCode); } } diff --git a/lib/src/executable.dart b/lib/src/executable.dart index ec37cef2b198c7f17ab6930224017f53b8ebb5f2..2c5fd1f14d29a077ce2723d9cda9ef7e4a9ace43 100644 --- a/lib/src/executable.dart +++ b/lib/src/executable.dart @@ -44,13 +44,13 @@ final _catchableSignals = Platform.isWindows /// /// Arguments from [args] will be passed to the spawned Dart application. /// -/// If [mode] is passed, it's used as the barback mode; it defaults to -/// [BarbackMode.RELEASE]. +/// If [checked] is true, the program is run in checked mode. If [mode] is +/// passed, it's used as the barback mode; it defaults to [BarbackMode.RELEASE]. /// /// Returns the exit code of the spawned app. Future<int> runExecutable(Entrypoint entrypoint, String package, String executable, Iterable<String> args, {bool isGlobal: false, - BarbackMode mode}) async { + bool checked: false, BarbackMode mode}) async { if (mode == null) mode = BarbackMode.RELEASE; // Make sure the package is an immediate dependency of the entrypoint or the @@ -84,7 +84,8 @@ Future<int> runExecutable(Entrypoint entrypoint, String package, // default mode for them to run. We can't run them in a different mode // using the snapshot. mode == BarbackMode.RELEASE) { - return _runCachedExecutable(entrypoint, localSnapshotPath, args); + return _runCachedExecutable(entrypoint, localSnapshotPath, args, + checked: checked); } // If the command has a path separator, then it's a path relative to the @@ -95,8 +96,7 @@ Future<int> runExecutable(Entrypoint entrypoint, String package, var vmArgs = []; // Run in checked mode. - // TODO(rnystrom): Make this configurable. - vmArgs.add("--checked"); + if (checked) vmArgs.add("--checked"); var executableUrl = await _executableUrl( entrypoint, package, executable, isGlobal: isGlobal, mode: mode); @@ -268,8 +268,8 @@ void _forwardSignals(Process process) { /// Runs the executable snapshot at [snapshotPath]. Future<int> _runCachedExecutable(Entrypoint entrypoint, String snapshotPath, - List<String> args) { - return runSnapshot(snapshotPath, args, checked: true, recompile: () { + List<String> args, {bool checked: false}) { + return runSnapshot(snapshotPath, args, checked: checked, recompile: () { log.fine("Precompiled executable is out of date."); return entrypoint.precompileExecutables(); }); diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart index 60eef15afae1be1b1d15ee9c9a263eec31431290..a9ca7d4ff7d7710951486107426ce32b422deaf2 100644 --- a/lib/src/global_packages.dart +++ b/lib/src/global_packages.dart @@ -329,12 +329,13 @@ class GlobalPackages { /// recompiled if the SDK has been upgraded since it was first compiled and /// then run. Otherwise, it will be run from source. /// - /// If [mode] is passed, it's used as the barback mode; it defaults to + /// If [checked] is true, the program is run in checked mode. If [mode] is + /// passed, it's used as the barback mode; it defaults to /// [BarbackMode.RELEASE]. /// /// Returns the exit code from the executable. Future<int> runExecutable(String package, String executable, - Iterable<String> args, {BarbackMode mode}) { + Iterable<String> args, {bool checked: false, BarbackMode mode}) { if (mode == null) mode = BarbackMode.RELEASE; var binDir = p.join(_directory, package, 'bin'); @@ -342,7 +343,7 @@ class GlobalPackages { !fileExists(p.join(binDir, '$executable.dart.snapshot'))) { return find(package).then((entrypoint) { return exe.runExecutable(entrypoint, package, executable, args, - mode: mode, isGlobal: true); + isGlobal: true, checked: checked, mode: mode); }); } @@ -353,7 +354,7 @@ class GlobalPackages { } var snapshotPath = p.join(binDir, '$executable.dart.snapshot'); - return exe.runSnapshot(snapshotPath, args, recompile: () { + return exe.runSnapshot(snapshotPath, args, checked: checked, recompile: () { log.fine("$package:$executable is out of date and needs to be " "recompiled."); return find(package) diff --git a/test/global/run/runs_script_in_checked_mode_test.dart b/test/global/run/runs_script_in_checked_mode_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..98fa94b3176346f736245cf41bded209af450228 --- /dev/null +++ b/test/global/run/runs_script_in_checked_mode_test.dart @@ -0,0 +1,28 @@ +// Copyright (c) 2014, 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:scheduled_test/scheduled_stream.dart'; + +import '../../descriptor.dart' as d; +import '../../test_pub.dart'; + +main() { + integration('runs a script in checked mode', () { + servePackages((builder) { + builder.serve("foo", "1.0.0", contents: [ + d.dir("bin", [ + d.file("script.dart", "main() { int a = true; }") + ]) + ]); + }); + + schedulePub(args: ["global", "activate", "foo"]); + + var pub = pubRun(global: true, args: ["--checked", "foo:script"]); + pub.stderr.expect(consumeThrough(contains( + "'bool' is not a subtype of type 'int' of 'a'"))); + pub.shouldExit(255); + }); +} diff --git a/test/global/run/runs_script_in_unchecked_mode_test.dart b/test/global/run/runs_script_in_unchecked_mode_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..87ccc29b14d6fc965b8ca9238929ba077b76de7e --- /dev/null +++ b/test/global/run/runs_script_in_unchecked_mode_test.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2014, 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. + +import 'package:scheduled_test/scheduled_test.dart'; + +import '../../descriptor.dart' as d; +import '../../test_pub.dart'; + +const SCRIPT = """ +main() { + int a = true; + print("no checks"); +} +"""; + +main() { + integration('runs a script in unchecked mode by default', () { + servePackages((builder) { + builder.serve("foo", "1.0.0", contents: [ + d.dir("bin", [ + d.file("script.dart", SCRIPT) + ]) + ]); + }); + + schedulePub(args: ["global", "activate", "foo"]); + + var pub = pubRun(global: true, args: ["foo:script"]); + pub.stdout.expect("no checks"); + pub.shouldExit(); + }); +} diff --git a/test/run/runs_the_script_in_checked_mode_test.dart b/test/run/runs_the_script_in_checked_mode_test.dart index 28a0fd946ba1f762d9f651d6a3d121a805f12f9c..b348f9a1360e543f5a73a8e710f2f453bedfc2d8 100644 --- a/test/run/runs_the_script_in_checked_mode_test.dart +++ b/test/run/runs_the_script_in_checked_mode_test.dart @@ -7,22 +7,16 @@ import 'package:scheduled_test/scheduled_test.dart'; import '../descriptor.dart' as d; import '../test_pub.dart'; -const SCRIPT = """ main() { - int a = true; -} -"""; - -main() { - integration('runs the script in checked mode by default', () { + integration('runs the script in checked mode with "--checked"', () { d.dir(appPath, [ d.appPubspec(), d.dir("bin", [ - d.file("script.dart", SCRIPT) + d.file("script.dart", "main() { int a = true; }") ]) ]).create(); - schedulePub(args: ["run", "bin/script"], + schedulePub(args: ["run", "--checked", "bin/script"], error: contains("'bool' is not a subtype of type 'int' of 'a'"), exitCode: 255); }); diff --git a/test/run/runs_the_script_in_unchecked_mode_test.dart b/test/run/runs_the_script_in_unchecked_mode_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..cdb2e52a3662e4a8187c315fad261559833a7172 --- /dev/null +++ b/test/run/runs_the_script_in_unchecked_mode_test.dart @@ -0,0 +1,28 @@ +// Copyright (c) 2014, 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. + +import 'package:scheduled_test/scheduled_test.dart'; + +import '../descriptor.dart' as d; +import '../test_pub.dart'; + +const SCRIPT = """ +main() { + int a = true; + print("no checks"); +} +"""; + +main() { + integration('runs the script in unchecked mode by default', () { + d.dir(appPath, [ + d.appPubspec(), + d.dir("bin", [ + d.file("script.dart", SCRIPT) + ]) + ]).create(); + + schedulePub(args: ["run", "bin/script"], output: contains("no checks")); + }); +}