From 1682e0bd5e984a5f88029c6e5ea625c099072323 Mon Sep 17 00:00:00 2001 From: Bob Nystrom <rnystrom@google.com> Date: Wed, 5 Aug 2015 17:12:38 -0700 Subject: [PATCH] Support "--checked" in pub run and global run. Fixes #1230. R=nweiz@google.com Review URL: https://codereview.chromium.org//1272813003 . --- lib/src/command/global_run.dart | 8 ++--- lib/src/command/run.dart | 4 ++- lib/src/executable.dart | 16 ++++----- lib/src/global_packages.dart | 9 ++--- .../run/runs_script_in_checked_mode_test.dart | 28 ++++++++++++++++ .../runs_script_in_unchecked_mode_test.dart | 33 +++++++++++++++++++ .../runs_the_script_in_checked_mode_test.dart | 12 ++----- ...uns_the_script_in_unchecked_mode_test.dart | 28 ++++++++++++++++ 8 files changed, 112 insertions(+), 26 deletions(-) create mode 100644 test/global/run/runs_script_in_checked_mode_test.dart create mode 100644 test/global/run/runs_script_in_unchecked_mode_test.dart create mode 100644 test/run/runs_the_script_in_unchecked_mode_test.dart diff --git a/lib/src/command/global_run.dart b/lib/src/command/global_run.dart index 7fc07a7a..ce0085cb 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 ad82c7df..9e60c816 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 ec37cef2..2c5fd1f1 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 60eef15a..a9ca7d4f 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 00000000..98fa94b3 --- /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 00000000..87ccc29b --- /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 28a0fd94..b348f9a1 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 00000000..cdb2e52a --- /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")); + }); +} -- GitLab