Version 2.15.0-117.0.dev

Merge commit '790d0b601cba52e826c53108a787a0a52d29a02b' into 'dev'
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index c93f71d..c5f54b2 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -15340,7 +15340,7 @@
   // #### Description
   //
   // The analyzer produces this diagnostic when a null-aware operator (`?.`,
-  // `?..`, `?[`, `?..[`, or `...?`) is used on a target that's known to be
+  // `?..`, `?[`, `?..[`, or `...?`) is used on a receiver that's known to be
   // non-nullable.
   //
   // #### Example
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 3b82cae..e13b744 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -6761,7 +6761,7 @@
 #### Description
 
 The analyzer produces this diagnostic when a null-aware operator (`?.`,
-`?..`, `?[`, `?..[`, or `...?`) is used on a target that's known to be
+`?..`, `?[`, `?..[`, or `...?`) is used on a receiver that's known to be
 non-nullable.
 
 #### Example
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index c254a6c..90b5822 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -937,7 +937,7 @@
   /// If none is found, [defaultTarget] is returned.
   ObjectAccessTarget _findDirectExtensionTypeMember(
       ExtensionType receiverType, Name name, int fileOffset,
-      {required ObjectAccessTarget defaultTarget}) {
+      {required ObjectAccessTarget defaultTarget, required bool isSetter}) {
     Member? targetMember;
     Member? targetTearoff;
     ProcedureKind? targetKind;
@@ -946,27 +946,37 @@
       if (descriptor.name == name) {
         switch (descriptor.kind) {
           case ExtensionMemberKind.Method:
-            targetMember = descriptor.member.asMember;
-            targetTearoff ??= targetMember;
-            targetKind = ProcedureKind.Method;
+            if (!isSetter) {
+              targetMember = descriptor.member.asMember;
+              targetTearoff ??= targetMember;
+              targetKind = ProcedureKind.Method;
+            }
             break;
           case ExtensionMemberKind.TearOff:
-            targetTearoff = descriptor.member.asMember;
+            if (!isSetter) {
+              targetTearoff = descriptor.member.asMember;
+            }
             break;
           case ExtensionMemberKind.Getter:
-            targetMember = descriptor.member.asMember;
-            targetTearoff = null;
-            targetKind = ProcedureKind.Getter;
+            if (!isSetter) {
+              targetMember = descriptor.member.asMember;
+              targetTearoff = null;
+              targetKind = ProcedureKind.Getter;
+            }
             break;
           case ExtensionMemberKind.Setter:
-            targetMember = descriptor.member.asMember;
-            targetTearoff = null;
-            targetKind = ProcedureKind.Setter;
+            if (isSetter) {
+              targetMember = descriptor.member.asMember;
+              targetTearoff = null;
+              targetKind = ProcedureKind.Setter;
+            }
             break;
           case ExtensionMemberKind.Operator:
-            targetMember = descriptor.member.asMember;
-            targetTearoff = null;
-            targetKind = ProcedureKind.Operator;
+            if (!isSetter) {
+              targetMember = descriptor.member.asMember;
+              targetTearoff = null;
+              targetKind = ProcedureKind.Operator;
+            }
             break;
           default:
             unhandled("${descriptor.kind}", "_findDirectExtensionMember",
@@ -1233,7 +1243,7 @@
     } else if (library.enableExtensionTypesInLibrary &&
         receiverBound is ExtensionType) {
       target = _findDirectExtensionTypeMember(receiverBound, name, fileOffset,
-          defaultTarget: const ObjectAccessTarget.missing());
+          isSetter: setter, defaultTarget: const ObjectAccessTarget.missing());
       if (target.kind == ObjectAccessTargetKind.missing) {
         target = _findShownExtensionTypeMember(receiverBound, name, fileOffset,
             isSetter: setter,
diff --git a/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart
new file mode 100644
index 0000000..2b50a93
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2021, 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.
+
+class A {}
+
+extension E on A {
+  void set foo(int value) {}
+  int get bar => 42;
+}
+
+test(E e) {
+  e.foo = 42; // Ok.
+  e.bar; // Ok.
+
+  e.foo; // Error.
+  e.bar = 42; // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.strong.expect b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.strong.expect
new file mode 100644
index 0000000..cd89df1
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.strong.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/access_setter_as_getter.dart:16:5: Error: The getter 'foo' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+//   e.foo; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/access_setter_as_getter.dart:17:5: Error: The setter 'bar' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'bar'.
+//   e.bar = 42; // Error.
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+extension E on self::A {
+  get bar = self::E|get#bar;
+  set foo = self::E|set#foo;
+}
+static method E|set#foo(lowered final self::A #this, core::int value) → void {}
+static method E|get#bar(lowered final self::A #this) → core::int
+  return 42;
+static method test(self::E e) → dynamic {
+  self::E|set#foo(e, 42);
+  self::E|get#bar(e);
+  invalid-expression "pkg/front_end/testcases/extension_types/access_setter_as_getter.dart:16:5: Error: The getter 'foo' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+  e.foo; // Error.
+    ^^^" in e{<unresolved>}.foo;
+  invalid-expression "pkg/front_end/testcases/extension_types/access_setter_as_getter.dart:17:5: Error: The setter 'bar' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'bar'.
+  e.bar = 42; // Error.
+    ^^^" in e{<unresolved>}.bar = 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.textual_outline.expect
new file mode 100644
index 0000000..d7b5f21
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+class A {}
+
+extension E on A {
+  void set foo(int value) {}
+  int get bar => 42;
+}
+
+test(E e) {}
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7a2c265
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class A {}
+
+extension E on A {
+  int get bar => 42;
+  void set foo(int value) {}
+}
+
+main() {}
+test(E e) {}
diff --git a/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.weak.expect b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.weak.expect
new file mode 100644
index 0000000..cd89df1
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.weak.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/access_setter_as_getter.dart:16:5: Error: The getter 'foo' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+//   e.foo; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/access_setter_as_getter.dart:17:5: Error: The setter 'bar' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'bar'.
+//   e.bar = 42; // Error.
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+extension E on self::A {
+  get bar = self::E|get#bar;
+  set foo = self::E|set#foo;
+}
+static method E|set#foo(lowered final self::A #this, core::int value) → void {}
+static method E|get#bar(lowered final self::A #this) → core::int
+  return 42;
+static method test(self::E e) → dynamic {
+  self::E|set#foo(e, 42);
+  self::E|get#bar(e);
+  invalid-expression "pkg/front_end/testcases/extension_types/access_setter_as_getter.dart:16:5: Error: The getter 'foo' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+  e.foo; // Error.
+    ^^^" in e{<unresolved>}.foo;
+  invalid-expression "pkg/front_end/testcases/extension_types/access_setter_as_getter.dart:17:5: Error: The setter 'bar' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'bar'.
+  e.bar = 42; // Error.
+    ^^^" in e{<unresolved>}.bar = 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.weak.outline.expect
new file mode 100644
index 0000000..b1f1b7a
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/access_setter_as_getter.dart.weak.outline.expect
@@ -0,0 +1,20 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+}
+extension E on self::A {
+  get bar = self::E|get#bar;
+  set foo = self::E|set#foo;
+}
+static method E|set#foo(lowered final self::A #this, core::int value) → void
+  ;
+static method E|get#bar(lowered final self::A #this) → core::int
+  ;
+static method test(self::E e) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index a88beba..4158e04 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -4,6 +4,7 @@
 
 const_functions/const_functions_const_factory: VerificationError
 constructor_tearoffs/lowering/invalid_redirect: VerificationError
+extension_types/access_setter_as_getter: ExpectationFileMismatchSerialized # Expected.
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
 extension_types/show_and_run_ceil: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple: ExpectationFileMismatchSerialized
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 90cc78d..1646398 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -10,6 +10,7 @@
 
 constructor_tearoffs/call_instantiation: TypeCheckError
 constructor_tearoffs/lowering/invalid_redirect: VerificationError
+extension_types/access_setter_as_getter: ExpectationFileMismatchSerialized # Expected.
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
 extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
 extension_types/show_and_run_ceil: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index c226f31..3187786 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -8,6 +8,7 @@
 
 constructor_tearoffs/call_instantiation: TypeCheckError
 constructor_tearoffs/lowering/invalid_redirect: VerificationError
+extension_types/access_setter_as_getter: ExpectationFileMismatchSerialized # Expected.
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
 extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
 extension_types/show_and_run_ceil: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 84e72b9..a018083 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -13,6 +13,7 @@
 
 constructor_tearoffs/call_instantiation: TypeCheckError
 constructor_tearoffs/lowering/invalid_redirect: VerificationError
+extension_types/access_setter_as_getter: ExpectationFileMismatchSerialized # Expected.
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
 extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
 extension_types/show_and_run_ceil: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/kernel/lib/transformations/async.dart b/pkg/kernel/lib/transformations/async.dart
index 621d51e..acca81a 100644
--- a/pkg/kernel/lib/transformations/async.dart
+++ b/pkg/kernel/lib/transformations/async.dart
@@ -529,19 +529,7 @@
     final R = continuationRewriter;
     var shouldName = seenAwait;
     var type = expr.getStaticType(_staticTypeContext);
-    Expression result = new VariableGet(asyncResult);
-    if (type is! DynamicType) {
-      int fileOffset = expr.operand.fileOffset;
-      if (fileOffset == TreeNode.noOffset) {
-        fileOffset = expr.fileOffset;
-      }
-      assert(fileOffset != TreeNode.noOffset);
-      result = new StaticInvocation(
-          continuationRewriter.helper.unsafeCast,
-          new Arguments(<Expression>[result], types: <DartType>[type])
-            ..fileOffset = fileOffset)
-        ..fileOffset = fileOffset;
-    }
+    Expression result = unsafeCastVariableGet(asyncResult, type);
 
     // The statements are in reverse order, so name the result first if
     // necessary and then add the two other statements in reverse.
diff --git a/runtime/observatory/tests/service/breakpoint_on_simple_conditions_test.dart b/runtime/observatory/tests/service/breakpoint_on_simple_conditions_test.dart
new file mode 100644
index 0000000..c8ab6c3
--- /dev/null
+++ b/runtime/observatory/tests/service/breakpoint_on_simple_conditions_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2021, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 15;
+const int LINE_B = 20;
+const int LINE_C = 24;
+const int LINE_D = 28;
+
+testMain() {
+  bool foo = false;
+  if (foo) { // LINE_A
+    print('1');
+  }
+
+  const bar = false;
+  if (bar) { // LINE_B
+    print('2');
+  }
+
+  while (foo) { // LINE_C
+    print('3');
+  }
+
+  while (bar) { // LINE_D
+    print('4');
+  }
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  setBreakpointAtLine(LINE_B),
+  setBreakpointAtLine(LINE_C),
+  setBreakpointAtLine(LINE_D),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_start: true);
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index fae5fd0..e5f8df6 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -61,6 +61,7 @@
 breakpoint_on_if_null_2_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoint_on_if_null_3_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoint_on_if_null_4_test: SkipByDesign # Debugger is disabled in AOT mode.
+breakpoint_on_simple_conditions_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoint_partfile_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoint_two_args_checked_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoints_with_mixin_test: SkipByDesign # Debugger is disabled in AOT mode.
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_on_simple_conditions_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_on_simple_conditions_test.dart
new file mode 100644
index 0000000..c8ab6c3
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_on_simple_conditions_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2021, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 15;
+const int LINE_B = 20;
+const int LINE_C = 24;
+const int LINE_D = 28;
+
+testMain() {
+  bool foo = false;
+  if (foo) { // LINE_A
+    print('1');
+  }
+
+  const bar = false;
+  if (bar) { // LINE_B
+    print('2');
+  }
+
+  while (foo) { // LINE_C
+    print('3');
+  }
+
+  while (bar) { // LINE_D
+    print('4');
+  }
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  setBreakpointAtLine(LINE_B),
+  setBreakpointAtLine(LINE_C),
+  setBreakpointAtLine(LINE_D),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_start: true);
diff --git a/runtime/observatory_2/tests/service_2/service_2_kernel.status b/runtime/observatory_2/tests/service_2/service_2_kernel.status
index 98dd984..5138ddd 100644
--- a/runtime/observatory_2/tests/service_2/service_2_kernel.status
+++ b/runtime/observatory_2/tests/service_2/service_2_kernel.status
@@ -61,6 +61,7 @@
 breakpoint_on_if_null_2_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoint_on_if_null_3_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoint_on_if_null_4_test: SkipByDesign # Debugger is disabled in AOT mode.
+breakpoint_on_simple_conditions_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoint_partfile_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoint_two_args_checked_test: SkipByDesign # Debugger is disabled in AOT mode.
 breakpoints_with_mixin_test: SkipByDesign # Debugger is disabled in AOT mode.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 03d5a27..d74fc3d 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1928,6 +1928,9 @@
       ASSERT(instructions.current->previous() != nullptr);
       instructions.current = instructions.current->previous();
     } else {
+      if (NeedsDebugStepCheck(stack(), position)) {
+        instructions = DebugStepCheck(position) + instructions;
+      }
       instructions += CheckBoolean(position);
       instructions += Constant(Bool::True());
       Value* right_value = Pop();
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 442248a..7406e5a 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -834,7 +834,8 @@
                                              String* name_to_modify,
                                              bool symbolize,
                                              bool obfuscate) {
-  if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_') {
+  if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_' &&
+      !library.IsNull()) {
     *name_to_modify = library.PrivateName(*name_to_modify);
     if (obfuscate && IG->obfuscate()) {
       const String& library_key = String::Handle(library.private_key());
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index fb7e37c..7e0034b 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2315,8 +2315,12 @@
   msg.value.as_string = const_cast<char*>(message);
   arr_values[0] = &msg;
   Dart_CObject stack;
-  stack.type = Dart_CObject_kString;
-  stack.value.as_string = const_cast<char*>(stacktrace);
+  if (stacktrace == NULL) {
+    stack.type = Dart_CObject_kNull;
+  } else {
+    stack.type = Dart_CObject_kString;
+    stack.value.as_string = const_cast<char*>(stacktrace);
+  }
   arr_values[1] = &stack;
 
   SendPort& listener = SendPort::Handle(current_zone());
diff --git a/runtime/vm/longjump.h b/runtime/vm/longjump.h
index c551584..60f514b 100644
--- a/runtime/vm/longjump.h
+++ b/runtime/vm/longjump.h
@@ -16,11 +16,9 @@
 
 class LongJumpScope : public StackResource {
  public:
-  LongJumpScope()
-      : StackResource(ThreadState::Current()),
-        top_(nullptr),
-        base_(thread()->long_jump_base()) {
-    thread()->set_long_jump_base(this);
+  explicit LongJumpScope(ThreadState* thread = ThreadState::Current())
+      : StackResource(thread), top_(nullptr), base_(thread->long_jump_base()) {
+    thread->set_long_jump_base(this);
   }
 
   ~LongJumpScope() {
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
index e7cc76e..ac2eef3 100644
--- a/runtime/vm/message_snapshot.cc
+++ b/runtime/vm/message_snapshot.cc
@@ -3162,6 +3162,7 @@
       cid = kDoubleCid;
       break;
     case Dart_CObject_kString: {
+      RELEASE_ASSERT(object->value.as_string != NULL);
       const uint8_t* utf8_str =
           reinterpret_cast<const uint8_t*>(object->value.as_string);
       intptr_t utf8_len = strlen(object->value.as_string);
@@ -3744,7 +3745,7 @@
 
   volatile bool has_exception = false;
   {
-    LongJumpScope jump;
+    LongJumpScope jump(thread);
     if (setjmp(*jump.Set()) == 0) {
       serializer.Serialize(obj);
     } else {
@@ -3819,8 +3820,13 @@
     return ReadObjectGraphCopyMessage(thread, message->persistent_handle());
   } else {
     RELEASE_ASSERT(message->IsSnapshot());
-    MessageDeserializer deserializer(thread, message);
-    return deserializer.Deserialize();
+    LongJumpScope jump(thread);
+    if (setjmp(*jump.Set()) == 0) {
+      MessageDeserializer deserializer(thread, message);
+      return deserializer.Deserialize();
+    } else {
+      return thread->StealStickyError();
+    }
   }
 }
 
diff --git a/tools/VERSION b/tools/VERSION
index 7671f3f..90c741d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 116
+PRERELEASE 117
 PRERELEASE_PATCH 0
\ No newline at end of file