Commit 03eaf1d1 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Fix hot reload (#5799)

I forgot that it was possible for the root view to get marked dirty
without getting a new widget. This fixes that case to work.
parent 59739abe
...@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart'; ...@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
import 'package:mojo/core.dart' as core; import 'package:mojo/core.dart' as core;
import 'package:sky_services/semantics/semantics.mojom.dart' as mojom; import 'package:sky_services/semantics/semantics.mojom.dart' as mojom;
...@@ -195,6 +196,7 @@ abstract class RendererBinding extends BindingBase implements SchedulerBinding, ...@@ -195,6 +196,7 @@ abstract class RendererBinding extends BindingBase implements SchedulerBinding,
/// list. /// list.
// //
// When editing the above, also update widgets/binding.dart's copy. // When editing the above, also update widgets/binding.dart's copy.
@protected
void beginFrame() { void beginFrame() {
assert(renderView != null); assert(renderView != null);
pipelineOwner.flushLayout(); pipelineOwner.flushLayout();
...@@ -208,7 +210,7 @@ abstract class RendererBinding extends BindingBase implements SchedulerBinding, ...@@ -208,7 +210,7 @@ abstract class RendererBinding extends BindingBase implements SchedulerBinding,
void reassembleApplication() { void reassembleApplication() {
super.reassembleApplication(); super.reassembleApplication();
pipelineOwner.reassemble(); pipelineOwner.reassemble();
beginFrame(); handleBeginFrame(null);
} }
@override @override
......
...@@ -491,11 +491,14 @@ class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObje ...@@ -491,11 +491,14 @@ class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObje
@override @override
void performRebuild() { void performRebuild() {
assert(_newWidget != null); if (_newWidget != null) {
final Widget newWidget = _newWidget; // _newWidget can be null if, for instance, we were rebuilt
_newWidget = null; // due to a reassemble.
final Widget newWidget = _newWidget;
_newWidget = null;
update(newWidget);
}
super.performRebuild(); super.performRebuild();
update(newWidget);
assert(_newWidget == null); assert(_newWidget == null);
} }
......
...@@ -1537,15 +1537,25 @@ class BuildOwner { ...@@ -1537,15 +1537,25 @@ class BuildOwner {
assert(_dirtyElements[index] != null); assert(_dirtyElements[index] != null);
assert(_dirtyElements[index]._inDirtyList); assert(_dirtyElements[index]._inDirtyList);
assert(!_dirtyElements[index]._active || _dirtyElements[index]._debugIsInScope(context)); assert(!_dirtyElements[index]._active || _dirtyElements[index]._debugIsInScope(context));
_dirtyElements[index].rebuild(); try {
_dirtyElements[index].rebuild();
} catch (e, stack) {
_debugReportException(
'while rebuilding dirty elements', e, stack,
informationCollector: (StringBuffer information) {
information.writeln('The element being rebuilt at the time was index $index of $dirtyCount:');
information.write(' ${_dirtyElements[index]}');
}
);
}
index += 1; index += 1;
if (dirtyCount < _dirtyElements.length) { if (dirtyCount < _dirtyElements.length) {
_dirtyElements.sort(_elementSort); _dirtyElements.sort(_elementSort);
dirtyCount = _dirtyElements.length; dirtyCount = _dirtyElements.length;
} }
} }
} finally {
assert(!_dirtyElements.any((BuildableElement element) => element._active && element.dirty)); assert(!_dirtyElements.any((BuildableElement element) => element._active && element.dirty));
} finally {
for (BuildableElement element in _dirtyElements) { for (BuildableElement element in _dirtyElements) {
assert(element._inDirtyList); assert(element._inDirtyList);
element._inDirtyList = false; element._inDirtyList = false;
...@@ -3149,11 +3159,14 @@ class MultiChildRenderObjectElement extends RenderObjectElement { ...@@ -3149,11 +3159,14 @@ class MultiChildRenderObjectElement extends RenderObjectElement {
} }
} }
void _debugReportException(String context, dynamic exception, StackTrace stack) { void _debugReportException(String context, dynamic exception, StackTrace stack, {
InformationCollector informationCollector
}) {
FlutterError.reportError(new FlutterErrorDetails( FlutterError.reportError(new FlutterErrorDetails(
exception: exception, exception: exception,
stack: stack, stack: stack,
library: 'widgets library', library: 'widgets library',
context: context context: context,
informationCollector: informationCollector,
)); ));
} }
// Copyright 2016 The Chromium Authors. 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:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('reassemble does not crash', (WidgetTester tester) async {
await tester.pumpWidget(new MaterialApp(
home: new Text('Hello World')
));
await tester.pump();
tester.binding.reassembleApplication();
await tester.pump();
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment