Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
57acc687
Unverified
Commit
57acc687
authored
Feb 18, 2020
by
Jonah Williams
Committed by
GitHub
Feb 18, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] ensure zoned errors are caught in new web runner (#50895)
parent
dfcf9beb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
180 additions
and
48 deletions
+180
-48
resident_web_runner.dart
...utter_tools/lib/src/build_runner/resident_web_runner.dart
+72
-47
resident_web_runner_test.dart
...er_tools/test/general.shard/resident_web_runner_test.dart
+108
-1
No files found.
packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
View file @
57acc687
...
...
@@ -4,14 +4,17 @@
import
'dart:async'
;
import
'package:dwds/dwds.dart'
;
import
'package:meta/meta.dart'
;
import
'package:vm_service/vm_service.dart'
as
vmservice
;
import
'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
hide
StackTrace
;
import
'../application_package.dart'
;
import
'../base/async_guard.dart'
;
import
'../base/common.dart'
;
import
'../base/file_system.dart'
;
import
'../base/io.dart'
;
import
'../base/logger.dart'
;
import
'../base/net.dart'
;
import
'../base/terminal.dart'
;
...
...
@@ -61,6 +64,10 @@ class DwdsWebRunnerFactory extends WebRunnerFactory {
}
}
const
String
kExitMessage
=
'Failed to establish connection with the application '
'instance in Chrome.
\n
This can happen if the websocket connection used by the '
'web tooling is unable to correctly establish a connection, for example due to a firewall.'
;
/// A hot-runner which handles browser specific delegation.
abstract
class
ResidentWebRunner
extends
ResidentRunner
{
ResidentWebRunner
(
...
...
@@ -393,45 +400,59 @@ class _ResidentWebRunner extends ResidentWebRunner {
final
int
hostPort
=
debuggingOptions
.
port
==
null
?
await
globals
.
os
.
findFreePort
()
:
int
.
tryParse
(
debuggingOptions
.
port
);
device
.
devFS
=
WebDevFS
(
hostname:
effectiveHostname
,
port:
hostPort
,
packagesFilePath:
packagesFilePath
,
urlTunneller:
urlTunneller
,
buildMode:
debuggingOptions
.
buildInfo
.
mode
,
enableDwds:
_enableDwds
,
entrypoint:
globals
.
fs
.
file
(
target
).
uri
,
);
final
Uri
url
=
await
device
.
devFS
.
create
();
if
(
debuggingOptions
.
buildInfo
.
isDebug
)
{
final
UpdateFSReport
report
=
await
_updateDevFS
(
fullRestart:
true
);
if
(!
report
.
success
)
{
globals
.
printError
(
'Failed to compile application.'
);
return
1
;
}
device
.
generator
.
accept
();
}
else
{
await
buildWeb
(
flutterProject
,
target
,
debuggingOptions
.
buildInfo
,
debuggingOptions
.
initializePlatform
,
dartDefines
,
false
,
);
try
{
return
await
asyncGuard
(()
async
{
device
.
devFS
=
WebDevFS
(
hostname:
effectiveHostname
,
port:
hostPort
,
packagesFilePath:
packagesFilePath
,
urlTunneller:
urlTunneller
,
buildMode:
debuggingOptions
.
buildInfo
.
mode
,
enableDwds:
_enableDwds
,
entrypoint:
globals
.
fs
.
file
(
target
).
uri
,
);
final
Uri
url
=
await
device
.
devFS
.
create
();
if
(
debuggingOptions
.
buildInfo
.
isDebug
)
{
final
UpdateFSReport
report
=
await
_updateDevFS
(
fullRestart:
true
);
if
(!
report
.
success
)
{
globals
.
printError
(
'Failed to compile application.'
);
return
1
;
}
device
.
generator
.
accept
();
}
else
{
await
buildWeb
(
flutterProject
,
target
,
debuggingOptions
.
buildInfo
,
debuggingOptions
.
initializePlatform
,
dartDefines
,
false
,
);
}
await
device
.
device
.
startApp
(
package
,
mainPath:
target
,
debuggingOptions:
debuggingOptions
,
platformArgs:
<
String
,
Object
>{
'uri'
:
url
.
toString
(),
},
);
return
attach
(
connectionInfoCompleter:
connectionInfoCompleter
,
appStartedCompleter:
appStartedCompleter
,
);
});
}
on
WebSocketException
{
throwToolExit
(
kExitMessage
);
}
on
ChromeDebugException
{
throwToolExit
(
kExitMessage
);
}
on
AppConnectionException
{
throwToolExit
(
kExitMessage
);
}
on
SocketException
{
throwToolExit
(
kExitMessage
);
}
await
device
.
device
.
startApp
(
package
,
mainPath:
target
,
debuggingOptions:
debuggingOptions
,
platformArgs:
<
String
,
Object
>{
'uri'
:
url
.
toString
(),
},
);
return
attach
(
connectionInfoCompleter:
connectionInfoCompleter
,
appStartedCompleter:
appStartedCompleter
,
);
return
0
;
}
@override
...
...
@@ -479,22 +500,25 @@ class _ResidentWebRunner extends ResidentWebRunner {
}
}
Duration
transferMarker
;
try
{
if
(!
deviceIsDebuggable
)
{
globals
.
printStatus
(
'Recompile complete. Page requires refresh.'
);
}
else
if
(
fullRestart
||
!
debuggingOptions
.
buildInfo
.
isDebug
)
{
}
else
if
(!
debuggingOptions
.
buildInfo
.
isDebug
)
{
// On non-debug builds, a hard refresh is required to ensure the
// up to date sources are loaded.
await
_wipConnection
?.
sendCommand
(
'Page.reload'
,
<
String
,
Object
>{
'ignoreCache'
:
!
debuggingOptions
.
buildInfo
.
isDebug
,
});
}
else
{
await
_wipConnection
?.
debugger
?.
sendCommand
(
'Runtime.evaluate'
,
params:
<
String
,
Object
>{
'expression'
:
'window.
\
$hotReloadHook
([
$reloadModules
])'
,
'awaitPromise'
:
true
,
'returnByValue'
:
true
,
});
transferMarker
=
timer
.
elapsed
;
await
_wipConnection
?.
debugger
?.
sendCommand
(
'Runtime.evaluate'
,
params:
<
String
,
Object
>{
'expression'
:
'window.
\
$hotReloadHook
([
$reloadModules
])'
,
'awaitPromise'
:
true
,
'returnByValue'
:
true
,
},
);
}
}
on
WipError
catch
(
err
)
{
globals
.
printError
(
err
.
toString
());
...
...
@@ -503,8 +527,8 @@ class _ResidentWebRunner extends ResidentWebRunner {
status
.
stop
();
}
final
String
verb
=
fullRestart
?
'Restarted'
:
'Reloaded'
;
globals
.
printStatus
(
'
$verb
application in
${getElapsedAsMilliseconds(timer.elapsed)}
.'
);
final
String
elapsed
=
getElapsedAsMilliseconds
(
timer
.
elapsed
)
;
globals
.
printStatus
(
'
Restarted application in
$elapsed
.'
);
// Don't track restart times for dart2js builds or web-server devices.
if
(
debuggingOptions
.
buildInfo
.
isDebug
&&
deviceIsDebuggable
)
{
...
...
@@ -517,6 +541,7 @@ class _ResidentWebRunner extends ResidentWebRunner {
fullRestart:
true
,
reason:
reason
,
overallTimeInMs:
timer
.
elapsed
.
inMilliseconds
,
transferTimeInMs:
timer
.
elapsed
.
inMilliseconds
-
transferMarker
.
inMilliseconds
).
send
();
}
return
OperationResult
.
ok
;
...
...
packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
View file @
57acc687
...
...
@@ -7,6 +7,7 @@ import 'dart:convert';
import
'package:dwds/dwds.dart'
;
import
'package:flutter_tools/src/base/common.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/base/terminal.dart'
;
import
'package:flutter_tools/src/build_info.dart'
;
...
...
@@ -316,7 +317,7 @@ void main() {
final
OperationResult
result
=
await
residentWebRunner
.
restart
(
fullRestart:
false
);
expect
(
testLogger
.
statusText
,
contains
(
'Re
load
ed application in'
));
expect
(
testLogger
.
statusText
,
contains
(
'Re
start
ed application in'
));
expect
(
result
.
code
,
0
);
verify
(
mockResidentCompiler
.
accept
()).
called
(
2
);
// ensure that analytics are sent.
...
...
@@ -836,6 +837,112 @@ void main() {
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
DelegateLogger
(
MockLogger
())
}));
test
(
'Successfully turns WebSocketException into ToolExit'
,
()
=>
testbed
.
run
(()
async
{
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
const
WebSocketException
();
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsToolExit
());
unhandledErrorCompleter
.
complete
();
await
expectation
;
}));
test
(
'Successfully turns AppConnectionException into ToolExit'
,
()
=>
testbed
.
run
(()
async
{
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
AppConnectionException
(
'Could not connect to application with appInstanceId: c0ae0750-ee91-11e9-cea6-35d95a968356'
);
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsToolExit
());
unhandledErrorCompleter
.
complete
();
await
expectation
;
}));
test
(
'Successfully turns ChromeDebugError into ToolExit'
,
()
=>
testbed
.
run
(()
async
{
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
ChromeDebugException
(<
String
,
dynamic
>{});
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsToolExit
());
unhandledErrorCompleter
.
complete
();
await
expectation
;
}));
test
(
'Rethrows Exception type'
,
()
=>
testbed
.
run
(()
async
{
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
Exception
(
'Something went wrong'
);
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsException
);
unhandledErrorCompleter
.
complete
();
await
expectation
;
}));
test
(
'Rethrows unknown exception type from web tooling'
,
()
=>
testbed
.
run
(()
async
{
_setupMocks
();
final
DelegateLogger
delegateLogger
=
globals
.
logger
as
DelegateLogger
;
final
MockStatus
mockStatus
=
MockStatus
();
delegateLogger
.
status
=
mockStatus
;
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
StateError
(
'Something went wrong'
);
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsStateError
);
unhandledErrorCompleter
.
complete
();
await
expectation
;
verify
(
mockStatus
.
stop
()).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
DelegateLogger
(
BufferLogger
(
terminal:
AnsiTerminal
(
stdio:
null
,
platform:
const
LocalPlatform
(),
),
outputPreferences:
OutputPreferences
.
test
(),
))
}));
}
class
MockChromeLauncher
extends
Mock
implements
ChromeLauncher
{}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment