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
7472fad1
Unverified
Commit
7472fad1
authored
Jun 19, 2019
by
Jonah Williams
Committed by
GitHub
Jun 19, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove most of the target logic for build web, cleanup rules (#34589)
parent
1d0aa02a
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
469 additions
and
484 deletions
+469
-484
build_script.dart
...ages/flutter_tools/lib/src/build_runner/build_script.dart
+459
-0
web_compilation_delegate.dart
..._tools/lib/src/build_runner/web_compilation_delegate.dart
+9
-474
resident_web_runner.dart
packages/flutter_tools/lib/src/resident_web_runner.dart
+1
-2
runner.dart
packages/flutter_tools/lib/src/test/runner.dart
+0
-3
compile.dart
packages/flutter_tools/lib/src/web/compile.dart
+0
-4
build_web_test.dart
packages/flutter_tools/test/commands/build_web_test.dart
+0
-1
No files found.
packages/flutter_tools/lib/src/build_runner/build_script.dart
0 → 100644
View file @
7472fad1
// Copyright 2019 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.
// ignore_for_file: implementation_imports
import
'dart:async'
;
import
'dart:convert'
;
// ignore: dart_convert_import
import
'dart:io'
;
// ignore: dart_io_import
import
'dart:isolate'
;
import
'package:analyzer/analyzer.dart'
;
// ignore: deprecated_member_use
import
'package:build_runner/build_runner.dart'
as
build_runner
;
import
'package:build/build.dart'
;
import
'package:build_config/build_config.dart'
;
import
'package:build_modules/build_modules.dart'
;
import
'package:build_modules/builders.dart'
;
import
'package:build_modules/src/module_builder.dart'
;
import
'package:build_modules/src/platform.dart'
;
import
'package:build_modules/src/workers.dart'
;
import
'package:build_runner_core/build_runner_core.dart'
as
core
;
import
'package:build_test/builder.dart'
;
import
'package:build_test/src/debug_test_builder.dart'
;
import
'package:build_web_compilers/build_web_compilers.dart'
;
import
'package:build_web_compilers/builders.dart'
;
import
'package:build_web_compilers/src/dev_compiler_bootstrap.dart'
;
import
'package:crypto/crypto.dart'
;
import
'package:path/path.dart'
as
path
;
// ignore: package_path_import
import
'package:scratch_space/scratch_space.dart'
;
import
'package:test_core/backend.dart'
;
const
String
ddcBootstrapExtension
=
'.dart.bootstrap.js'
;
const
String
jsEntrypointExtension
=
'.dart.js'
;
const
String
jsEntrypointSourceMapExtension
=
'.dart.js.map'
;
const
String
jsEntrypointArchiveExtension
=
'.dart.js.tar.gz'
;
const
String
digestsEntrypointExtension
=
'.digests'
;
const
String
jsModuleErrorsExtension
=
'.ddc.js.errors'
;
const
String
jsModuleExtension
=
'.ddc.js'
;
const
String
jsSourceMapExtension
=
'.ddc.js.map'
;
final
DartPlatform
flutterWebPlatform
=
DartPlatform
.
register
(
'flutter_web'
,
<
String
>[
'async'
,
'collection'
,
'convert'
,
'core'
,
'developer'
,
'html'
,
'html_common'
,
'indexed_db'
,
'js'
,
'js_util'
,
'math'
,
'svg'
,
'typed_data'
,
'web_audio'
,
'web_gl'
,
'web_sql'
,
'_internal'
,
// Flutter web specific libraries.
'ui'
,
'_engine'
,
'io'
,
'isolate'
,
]);
/// The builders required to compile a Flutter application to the web.
final
List
<
core
.
BuilderApplication
>
builders
=
<
core
.
BuilderApplication
>[
core
.
apply
(
'flutter_tools:test_bootstrap'
,
<
BuilderFactory
>[
(
BuilderOptions
options
)
=>
const
DebugTestBuilder
(),
(
BuilderOptions
options
)
=>
const
FlutterWebTestBootstrapBuilder
(),
],
core
.
toRoot
(),
hideOutput:
true
,
defaultGenerateFor:
const
InputSet
(
include:
<
String
>[
'test/**'
,
],
),
),
core
.
apply
(
'flutter_tools:shell'
,
<
BuilderFactory
>[
(
BuilderOptions
options
)
=>
const
FlutterWebShellBuilder
(),
],
core
.
toRoot
(),
hideOutput:
true
,
defaultGenerateFor:
const
InputSet
(
include:
<
String
>[
'lib/**'
,
'web/**'
,
],
),
),
core
.
apply
(
'flutter_tools:module_library'
,
<
Builder
Function
(
BuilderOptions
)>[
moduleLibraryBuilder
],
core
.
toAllPackages
(),
isOptional:
true
,
hideOutput:
true
,
appliesBuilders:
<
String
>[
'flutter_tools:module_cleanup'
]),
core
.
apply
(
'flutter_tools:ddc_modules'
,
<
Builder
Function
(
BuilderOptions
)>[
(
BuilderOptions
options
)
=>
MetaModuleBuilder
(
flutterWebPlatform
),
(
BuilderOptions
options
)
=>
MetaModuleCleanBuilder
(
flutterWebPlatform
),
(
BuilderOptions
options
)
=>
ModuleBuilder
(
flutterWebPlatform
),
],
core
.
toNoneByDefault
(),
isOptional:
true
,
hideOutput:
true
,
appliesBuilders:
<
String
>[
'flutter_tools:module_cleanup'
]),
core
.
apply
(
'flutter_tools:ddc'
,
<
Builder
Function
(
BuilderOptions
)>[
(
BuilderOptions
builderOptions
)
=>
KernelBuilder
(
platformSdk:
builderOptions
.
config
[
'flutterWebSdk'
],
summaryOnly:
true
,
sdkKernelPath:
path
.
join
(
'kernel'
,
'flutter_ddc_sdk.dill'
),
outputExtension:
ddcKernelExtension
,
platform:
flutterWebPlatform
,
librariesPath:
'libraries.json'
,
),
(
BuilderOptions
builderOptions
)
=>
DevCompilerBuilder
(
useIncrementalCompiler:
true
,
platform:
flutterWebPlatform
,
platformSdk:
builderOptions
.
config
[
'flutterWebSdk'
],
sdkKernelPath:
path
.
join
(
'kernel'
,
'flutter_ddc_sdk.dill'
),
),
],
core
.
toAllPackages
(),
isOptional:
true
,
hideOutput:
true
,
appliesBuilders:
<
String
>[
'flutter_tools:ddc_modules'
]),
core
.
apply
(
'flutter_tools:entrypoint'
,
<
BuilderFactory
>[
(
BuilderOptions
options
)
=>
FlutterWebEntrypointBuilder
(
options
.
config
[
'release'
]
??
false
,
options
.
config
[
'flutterWebSdk'
],
),
],
core
.
toRoot
(),
hideOutput:
true
,
defaultGenerateFor:
const
InputSet
(
include:
<
String
>[
'lib/**_web_entrypoint.dart'
,
],
),
),
core
.
apply
(
'flutter_tools:test_entrypoint'
,
<
BuilderFactory
>[
(
BuilderOptions
options
)
=>
const
FlutterWebTestEntrypointBuilder
(),
],
core
.
toRoot
(),
hideOutput:
true
,
defaultGenerateFor:
const
InputSet
(
include:
<
String
>[
'test/**_test.dart.browser_test.dart'
,
],
),
),
core
.
applyPostProcess
(
'flutter_tools:module_cleanup'
,
moduleCleanup
,
defaultGenerateFor:
const
InputSet
())
];
/// The entrypoint to this build script.
Future
<
void
>
main
(
List
<
String
>
args
,
[
SendPort
sendPort
])
async
{
core
.
overrideGeneratedOutputDirectory
(
'flutter_web'
);
final
int
result
=
await
build_runner
.
run
(
args
,
builders
);
sendPort
?.
send
(
result
);
}
/// A ddc-only entrypoint builder that respects the Flutter target flag.
class
FlutterWebTestEntrypointBuilder
implements
Builder
{
const
FlutterWebTestEntrypointBuilder
();
@override
Map
<
String
,
List
<
String
>>
get
buildExtensions
=>
const
<
String
,
List
<
String
>>{
'.dart'
:
<
String
>[
ddcBootstrapExtension
,
jsEntrypointExtension
,
jsEntrypointSourceMapExtension
,
jsEntrypointArchiveExtension
,
digestsEntrypointExtension
,
],
};
@override
Future
<
void
>
build
(
BuildStep
buildStep
)
async
{
log
.
info
(
'building for target
${buildStep.inputId.path}
'
);
await
bootstrapDdc
(
buildStep
,
platform:
flutterWebPlatform
);
}
}
/// A ddc-only entrypoint builder that respects the Flutter target flag.
class
FlutterWebEntrypointBuilder
implements
Builder
{
const
FlutterWebEntrypointBuilder
(
this
.
release
,
this
.
flutterWebSdk
);
final
bool
release
;
final
String
flutterWebSdk
;
@override
Map
<
String
,
List
<
String
>>
get
buildExtensions
=>
const
<
String
,
List
<
String
>>{
'.dart'
:
<
String
>[
ddcBootstrapExtension
,
jsEntrypointExtension
,
jsEntrypointSourceMapExtension
,
jsEntrypointArchiveExtension
,
digestsEntrypointExtension
,
],
};
@override
Future
<
void
>
build
(
BuildStep
buildStep
)
async
{
if
(
release
)
{
await
bootstrapDart2Js
(
buildStep
,
flutterWebSdk
);
}
else
{
await
bootstrapDdc
(
buildStep
,
platform:
flutterWebPlatform
);
}
}
}
/// Bootstraps the test entrypoint.
class
FlutterWebTestBootstrapBuilder
implements
Builder
{
const
FlutterWebTestBootstrapBuilder
();
@override
Map
<
String
,
List
<
String
>>
get
buildExtensions
=>
const
<
String
,
List
<
String
>>{
'_test.dart'
:
<
String
>[
'_test.dart.browser_test.dart'
,
]
};
@override
Future
<
void
>
build
(
BuildStep
buildStep
)
async
{
final
AssetId
id
=
buildStep
.
inputId
;
final
String
contents
=
await
buildStep
.
readAsString
(
id
);
final
String
assetPath
=
id
.
pathSegments
.
first
==
'lib'
?
path
.
url
.
join
(
'packages'
,
id
.
package
,
id
.
path
)
:
id
.
path
;
final
Metadata
metadata
=
parseMetadata
(
assetPath
,
contents
,
Runtime
.
builtIn
.
map
((
Runtime
runtime
)
=>
runtime
.
name
).
toSet
());
if
(
metadata
.
testOn
.
evaluate
(
SuitePlatform
(
Runtime
.
chrome
)))
{
await
buildStep
.
writeAsString
(
id
.
addExtension
(
'.browser_test.dart'
),
'''
import '
dart:
ui
' as ui;
import '
dart:
html
';
import '
dart:
js
';
import '
package:
stream_channel
/
stream_channel
.
dart
';
import '
package:
test_api
/
src
/
backend
/
stack_trace_formatter
.
dart
'; // ignore: implementation_imports
import '
package:
test_api
/
src
/
util
/
stack_trace_mapper
.
dart
'; // ignore: implementation_imports
import '
package:
test_api
/
src
/
remote_listener
.
dart
'; // ignore: implementation_imports
import '
package:
test_api
/
src
/
suite_channel_manager
.
dart
'; // ignore: implementation_imports
import "
${path.url.basename(id.path)}
" as test;
Future<void> main() async {
// Extra initialization for flutter_web.
// The following parameters are hard-coded in Flutter'
s
test
embedder
.
Since
// we don't have an embedder yet this is the lowest-most layer we can put
// this stuff in.
await
ui
.
webOnlyInitializeEngine
();
// TODO(flutterweb): remove need for dynamic cast.
(
ui
.
window
as
dynamic
).
debugOverrideDevicePixelRatio
(
3.0
);
(
ui
.
window
as
dynamic
).
webOnlyDebugPhysicalSizeOverride
=
const
ui
.
Size
(
2400
,
1800
);
internalBootstrapBrowserTest
(()
=>
test
.
main
);
}
void
internalBootstrapBrowserTest
(
Function
getMain
())
{
var
channel
=
serializeSuite
(
getMain
,
hidePrints:
false
,
beforeLoad:
()
async
{
var
serialized
=
await
suiteChannel
(
"test.browser.mapper"
).
stream
.
first
as
Map
;
if
(
serialized
==
null
)
return
;
});
postMessageChannel
().
pipe
(
channel
);
}
StreamChannel
serializeSuite
(
Function
getMain
(),
{
bool
hidePrints
=
true
,
Future
beforeLoad
()})
=>
RemoteListener
.
start
(
getMain
,
hidePrints:
hidePrints
,
beforeLoad:
beforeLoad
);
StreamChannel
suiteChannel
(
String
name
)
{
var
manager
=
SuiteChannelManager
.
current
;
if
(
manager
==
null
)
{
throw
StateError
(
'suiteChannel() may only be called within a test worker.'
);
}
return
manager
.
connectOut
(
name
);
}
StreamChannel
postMessageChannel
(
)
{
var
controller
=
StreamChannelController
(
sync:
true
);
window
.
onMessage
.
firstWhere
((
message
)
{
return
message
.
origin
==
window
.
location
.
origin
&&
message
.
data
==
"port"
;
}).
then
((
message
)
{
var
port
=
message
.
ports
.
first
;
var
portSubscription
=
port
.
onMessage
.
listen
((
message
)
{
controller
.
local
.
sink
.
add
(
message
.
data
);
});
controller
.
local
.
stream
.
listen
((
data
)
{
port
.
postMessage
({
"data"
:
data
});
},
onDone:
()
{
port
.
postMessage
({
"event"
:
"done"
});
portSubscription
.
cancel
();
});
});
context
[
'parent'
].
callMethod
(
'postMessage'
,
[
JsObject
.
jsify
({
"href"
:
window
.
location
.
href
,
"ready"
:
true
}),
window
.
location
.
origin
,
]);
return
controller
.
foreign
;
}
void
setStackTraceMapper
(
StackTraceMapper
mapper
)
{
var
formatter
=
StackTraceFormatter
.
current
;
if
(
formatter
==
null
)
{
throw
StateError
(
'setStackTraceMapper() may only be called within a test worker.'
);
}
formatter
.
configure
(
mapper:
mapper
);
}
''');
}
}
}
/// A shell builder which generates the web specific entrypoint.
class FlutterWebShellBuilder implements Builder {
const FlutterWebShellBuilder();
@override
Future<void> build(BuildStep buildStep) async {
final AssetId dartEntrypointId = buildStep.inputId;
final bool isAppEntrypoint = await _isAppEntryPoint(dartEntrypointId, buildStep);
if (!isAppEntrypoint) {
return;
}
final AssetId outputId = buildStep.inputId.changeExtension('
_web_entrypoint
.
dart
');
await buildStep.writeAsString(outputId, '''
import
'dart:ui'
as
ui
;
import
"
${path.url.basename(buildStep.inputId.path)}
"
as
entrypoint
;
Future
<
void
>
main
()
async
{
await
ui
.
webOnlyInitializePlatform
();
entrypoint
.
main
();
}
''');
}
@override
Map<String, List<String>> get buildExtensions => const <String, List<String>>{
'
.
dart
': <String>['
_web_entrypoint
.
dart
'],
};
}
Future<void> bootstrapDart2Js(BuildStep buildStep, String flutterWebSdk) async {
final AssetId dartEntrypointId = buildStep.inputId;
final AssetId moduleId = dartEntrypointId.changeExtension(moduleExtension(flutterWebPlatform));
final Module module = Module.fromJson(json.decode(await buildStep.readAsString(moduleId)));
final List<Module> allDeps = await module.computeTransitiveDependencies(buildStep, throwIfUnsupported: false)..add(module);
final ScratchSpace scratchSpace = await buildStep.fetchResource(scratchSpaceResource);
final Iterable<AssetId> allSrcs = allDeps.expand((Module module) => module.sources);
await scratchSpace.ensureAssets(allSrcs, buildStep);
final String packageFile = await _createPackageFile(allSrcs, buildStep, scratchSpace);
final String dartPath = dartEntrypointId.path.startsWith('
lib
/
')
? '
package:
$
{
dartEntrypointId
.
package
}/
'
'
$
{
dartEntrypointId
.
path
.
substring
(
'lib/'
.
length
)}
'
: dartEntrypointId.path;
final String jsOutputPath =
'
$
{
path
.
withoutExtension
(
dartPath
.
replaceFirst
(
'package:'
,
'packages/'
))}
'
'
$jsEntrypointExtension
';
final String flutterWebSdkPath = flutterWebSdk;
final String librariesPath = path.join(flutterWebSdkPath, '
libraries
.
json
');
final List<String> args = <String>[
'
--
libraries
-
spec
=
"
$librariesPath
"',
'
-
O4
',
'
-
o
',
'
$jsOutputPath
',
'
--
packages
=
"
$packageFile
"',
'
-
Ddart
.
vm
.
product
=
true
',
dartPath,
];
final Dart2JsBatchWorkerPool dart2js = await buildStep.fetchResource(dart2JsWorkerResource);
final Dart2JsResult result = await dart2js.compile(args);
final AssetId jsOutputId = dartEntrypointId.changeExtension(jsEntrypointExtension);
final File jsOutputFile = scratchSpace.fileFor(jsOutputId);
if (result.succeeded && jsOutputFile.existsSync()) {
log.info(result.output);
// Explicitly write out the original js file and sourcemap.
await scratchSpace.copyOutput(jsOutputId, buildStep);
final AssetId jsSourceMapId =
dartEntrypointId.changeExtension(jsEntrypointSourceMapExtension);
await _copyIfExists(jsSourceMapId, scratchSpace, buildStep);
} else {
log.severe(result.output);
}
}
Future<void> _copyIfExists(
AssetId id, ScratchSpace scratchSpace, AssetWriter writer) async {
final File file = scratchSpace.fileFor(id);
if (file.existsSync()) {
await scratchSpace.copyOutput(id, writer);
}
}
/// Creates a `.packages` file unique to this entrypoint at the root of the
/// scratch space and returns it'
s
filename
.
///
/// Since mulitple invocations of Dart2Js will share a scratch space and we only
/// know the set of packages involved the current entrypoint we can't construct
/// a `.packages` file that will work for all invocations of Dart2Js so a unique
/// file is created for every entrypoint that is run.
///
/// The filename is based off the MD5 hash of the asset path so that files are
/// unique regarless of situations like `web/foo/bar.dart` vs
/// `web/foo-bar.dart`.
Future
<
String
>
_createPackageFile
(
Iterable
<
AssetId
>
inputSources
,
BuildStep
buildStep
,
ScratchSpace
scratchSpace
)
async
{
final
Uri
inputUri
=
buildStep
.
inputId
.
uri
;
final
String
packageFileName
=
'.package-
${md5.convert(inputUri.toString().codeUnits)}
'
;
final
File
packagesFile
=
scratchSpace
.
fileFor
(
AssetId
(
buildStep
.
inputId
.
package
,
packageFileName
));
final
Set
<
String
>
packageNames
=
inputSources
.
map
((
AssetId
s
)
=>
s
.
package
).
toSet
();
final
String
packagesFileContent
=
packageNames
.
map
((
String
name
)
=>
'
$name
:packages/
$name
/'
).
join
(
'
\n
'
);
await
packagesFile
.
writeAsString
(
'# Generated for
$inputUri
\n
$packagesFileContent
'
);
return
packageFileName
;
}
/// Returns whether or not [dartId] is an app entrypoint (basically, whether
/// or not it has a `main` function).
Future
<
bool
>
_isAppEntryPoint
(
AssetId
dartId
,
AssetReader
reader
)
async
{
assert
(
dartId
.
extension
==
'.dart'
);
// Skip reporting errors here, dartdevc will report them later with nicer
// formatting.
final
CompilationUnit
parsed
=
parseCompilationUnit
(
await
reader
.
readAsString
(
dartId
),
suppressErrors:
true
);
// Allow two or fewer arguments so that entrypoints intended for use with
// [spawnUri] get counted.
return
parsed
.
declarations
.
any
((
CompilationUnitMember
node
)
{
return
node
is
FunctionDeclaration
&&
node
.
name
.
name
==
'main'
&&
node
.
functionExpression
.
parameters
.
parameters
.
length
<=
2
;
});
}
packages/flutter_tools/lib/src/build_runner/web_compilation_delegate.dart
View file @
7472fad1
...
...
@@ -4,31 +4,16 @@
// ignore_for_file: implementation_imports
import
'dart:async'
;
import
'dart:io'
as
io
;
// ignore: dart_io_import
import
'package:build/build.dart'
;
import
'package:build_config/build_config.dart'
;
import
'package:build_modules/build_modules.dart'
;
import
'package:build_modules/builders.dart'
;
import
'package:build_modules/src/module_builder.dart'
;
import
'package:build_modules/src/platform.dart'
;
import
'package:build_modules/src/workers.dart'
;
import
'package:build_runner_core/build_runner_core.dart'
as
core
;
import
'package:build_runner_core/src/asset_graph/graph.dart'
;
import
'package:build_runner_core/src/asset_graph/node.dart'
;
import
'package:build_runner_core/src/generate/build_impl.dart'
;
import
'package:build_runner_core/src/generate/options.dart'
;
import
'package:build_test/builder.dart'
;
import
'package:build_test/src/debug_test_builder.dart'
;
import
'package:build_web_compilers/build_web_compilers.dart'
;
import
'package:build_web_compilers/builders.dart'
;
import
'package:build_web_compilers/src/dev_compiler_bootstrap.dart'
;
import
'package:crypto/crypto.dart'
;
import
'package:logging/logging.dart'
;
import
'package:meta/meta.dart'
;
import
'package:path/path.dart'
as
path
;
import
'package:scratch_space/scratch_space.dart'
;
import
'package:test_core/backend.dart'
;
import
'package:watcher/watcher.dart'
;
import
'../artifacts.dart'
;
...
...
@@ -36,152 +21,10 @@ import '../base/file_system.dart';
import
'../base/logger.dart'
;
import
'../base/platform.dart'
;
import
'../compile.dart'
;
import
'../convert.dart'
;
import
'../dart/package_map.dart'
;
import
'../globals.dart'
;
import
'../web/compile.dart'
;
const
String
ddcBootstrapExtension
=
'.dart.bootstrap.js'
;
const
String
jsEntrypointExtension
=
'.dart.js'
;
const
String
jsEntrypointSourceMapExtension
=
'.dart.js.map'
;
const
String
jsEntrypointArchiveExtension
=
'.dart.js.tar.gz'
;
const
String
digestsEntrypointExtension
=
'.digests'
;
const
String
jsModuleErrorsExtension
=
'.ddc.js.errors'
;
const
String
jsModuleExtension
=
'.ddc.js'
;
const
String
jsSourceMapExtension
=
'.ddc.js.map'
;
final
DartPlatform
flutterWebPlatform
=
DartPlatform
.
register
(
'flutter_web'
,
<
String
>[
'async'
,
'collection'
,
'convert'
,
'core'
,
'developer'
,
'html'
,
'html_common'
,
'indexed_db'
,
'js'
,
'js_util'
,
'math'
,
'svg'
,
'typed_data'
,
'web_audio'
,
'web_gl'
,
'web_sql'
,
'_internal'
,
// Flutter web specific libraries.
'ui'
,
'_engine'
,
'io'
,
'isolate'
,
]);
/// The build application to compile a flutter application to the web.
final
List
<
core
.
BuilderApplication
>
builders
=
<
core
.
BuilderApplication
>[
core
.
apply
(
'flutter_tools|test_bootstrap'
,
<
BuilderFactory
>[
(
BuilderOptions
options
)
=>
const
DebugTestBuilder
(),
(
BuilderOptions
options
)
=>
const
FlutterWebTestBootstrapBuilder
(),
],
core
.
toRoot
(),
hideOutput:
true
,
defaultGenerateFor:
const
InputSet
(
include:
<
String
>[
'test/**'
,
],
),
),
core
.
apply
(
'flutter_tools|shell'
,
<
BuilderFactory
>[
(
BuilderOptions
options
)
=>
FlutterWebShellBuilder
(
options
.
config
[
'targets'
]
??
<
String
>[
'lib/main.dart'
]
),
],
core
.
toRoot
(),
hideOutput:
true
,
defaultGenerateFor:
const
InputSet
(
include:
<
String
>[
'lib/**'
,
'web/**'
,
],
),
),
core
.
apply
(
'flutter_tools|module_library'
,
<
Builder
Function
(
BuilderOptions
)>[
moduleLibraryBuilder
],
core
.
toAllPackages
(),
isOptional:
true
,
hideOutput:
true
,
appliesBuilders:
<
String
>[
'flutter_tools|module_cleanup'
]),
core
.
apply
(
'flutter_tools|ddc_modules'
,
<
Builder
Function
(
BuilderOptions
)>[
(
BuilderOptions
options
)
=>
MetaModuleBuilder
(
flutterWebPlatform
),
(
BuilderOptions
options
)
=>
MetaModuleCleanBuilder
(
flutterWebPlatform
),
(
BuilderOptions
options
)
=>
ModuleBuilder
(
flutterWebPlatform
),
],
core
.
toNoneByDefault
(),
isOptional:
true
,
hideOutput:
true
,
appliesBuilders:
<
String
>[
'flutter_tools|module_cleanup'
]),
core
.
apply
(
'flutter_tools|ddc'
,
<
Builder
Function
(
BuilderOptions
)>[
(
BuilderOptions
builderOptions
)
=>
KernelBuilder
(
platformSdk:
artifacts
.
getArtifactPath
(
Artifact
.
flutterWebSdk
),
summaryOnly:
true
,
sdkKernelPath:
path
.
join
(
'kernel'
,
'flutter_ddc_sdk.dill'
),
outputExtension:
ddcKernelExtension
,
platform:
flutterWebPlatform
,
librariesPath:
'libraries.json'
,
),
(
BuilderOptions
builderOptions
)
=>
DevCompilerBuilder
(
useIncrementalCompiler:
false
,
platform:
flutterWebPlatform
,
platformSdk:
artifacts
.
getArtifactPath
(
Artifact
.
flutterWebSdk
),
sdkKernelPath:
path
.
join
(
'kernel'
,
'flutter_ddc_sdk.dill'
),
),
],
core
.
toAllPackages
(),
isOptional:
true
,
hideOutput:
true
,
appliesBuilders:
<
String
>[
'flutter_tools|ddc_modules'
]),
core
.
apply
(
'flutter_tools|entrypoint'
,
<
BuilderFactory
>[
(
BuilderOptions
options
)
=>
FlutterWebEntrypointBuilder
(
options
.
config
[
'targets'
]
??
<
String
>[
'lib/main.dart'
],
options
.
config
[
'release'
],
),
],
core
.
toRoot
(),
hideOutput:
true
,
defaultGenerateFor:
const
InputSet
(
include:
<
String
>[
'lib/**'
,
],
),
),
core
.
apply
(
'flutter_tools|test_entrypoint'
,
<
BuilderFactory
>[
(
BuilderOptions
options
)
=>
FlutterWebTestEntrypointBuilder
(
options
.
config
[
'targets'
]
??
const
<
String
>[]
),
],
core
.
toRoot
(),
hideOutput:
true
,
defaultGenerateFor:
const
InputSet
(
include:
<
String
>[
'test/**_test.dart.browser_test.dart'
,
],
),
),
core
.
applyPostProcess
(
'flutter_tools|module_cleanup'
,
moduleCleanup
,
defaultGenerateFor:
const
InputSet
())
];
import
'build_script.dart'
;
/// A build_runner specific implementation of the [WebCompilationProxy].
class
BuildRunnerWebCompilationProxy
extends
WebCompilationProxy
{
...
...
@@ -193,8 +36,7 @@ class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
@override
Future
<
bool
>
initialize
({
@required
Directory
projectDirectory
,
@required
List
<
String
>
targets
,
Directory
projectDirectory
,
String
testOutputDir
,
bool
release
=
false
,
})
async
{
...
...
@@ -238,14 +80,11 @@ class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
),
),
};
final
Status
status
=
logger
.
startProgress
(
'Compiling
${targets.first}
for the Web...'
,
timeout:
null
);
core
.
BuildResult
result
;
try
{
result
=
await
_runBuilder
(
buildEnvironment
,
buildOptions
,
targets
,
release
,
buildDirs
,
);
...
...
@@ -255,7 +94,6 @@ class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
result
=
await
_runBuilder
(
buildEnvironment
,
buildOptions
,
targets
,
release
,
buildDirs
,
);
...
...
@@ -265,13 +103,10 @@ class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
result
=
await
_runBuilder
(
buildEnvironment
,
buildOptions
,
targets
,
release
,
buildDirs
,
);
return
result
.
status
==
core
.
BuildStatus
.
success
;
}
finally
{
status
.
stop
();
}
}
...
...
@@ -293,24 +128,22 @@ class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
return
result
.
status
==
core
.
BuildStatus
.
success
;
}
Future
<
core
.
BuildResult
>
_runBuilder
(
core
.
BuildEnvironment
buildEnvironment
,
BuildOptions
buildOptions
,
List
<
String
>
targets
,
bool
release
,
Set
<
core
.
BuildDirectory
>
buildDirs
)
async
{
Future
<
core
.
BuildResult
>
_runBuilder
(
core
.
BuildEnvironment
buildEnvironment
,
BuildOptions
buildOptions
,
bool
release
,
Set
<
core
.
BuildDirectory
>
buildDirs
)
async
{
_builder
=
await
BuildImpl
.
create
(
buildOptions
,
buildEnvironment
,
builders
,
<
String
,
Map
<
String
,
dynamic
>>{
'flutter_tools|entrypoint'
:
<
String
,
dynamic
>{
'targets'
:
targets
,
'flutter_tools:ddc'
:
<
String
,
dynamic
>{
'flutterWebSdk'
:
artifacts
.
getArtifactPath
(
Artifact
.
flutterWebSdk
),
},
'flutter_tools:entrypoint'
:
<
String
,
dynamic
>{
'release'
:
release
,
'flutterWebSdk'
:
artifacts
.
getArtifactPath
(
Artifact
.
flutterWebSdk
),
},
'flutter_tools|test_entrypoint'
:
<
String
,
dynamic
>{
'targets'
:
targets
,
'flutter_tools:test_entrypoint'
:
<
String
,
dynamic
>{
'release'
:
release
,
},
'flutter_tools|shell'
:
<
String
,
dynamic
>{
'targets'
:
targets
,
}
},
isReleaseBuild:
false
,
);
...
...
@@ -364,301 +197,3 @@ class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
}
}
}
/// A ddc-only entrypoint builder that respects the Flutter target flag.
class
FlutterWebTestEntrypointBuilder
implements
Builder
{
const
FlutterWebTestEntrypointBuilder
(
this
.
targets
);
final
List
<
String
>
targets
;
@override
Map
<
String
,
List
<
String
>>
get
buildExtensions
=>
const
<
String
,
List
<
String
>>{
'.dart'
:
<
String
>[
ddcBootstrapExtension
,
jsEntrypointExtension
,
jsEntrypointSourceMapExtension
,
jsEntrypointArchiveExtension
,
digestsEntrypointExtension
,
],
};
@override
Future
<
void
>
build
(
BuildStep
buildStep
)
async
{
bool
matches
=
false
;
for
(
String
target
in
targets
)
{
if
(
buildStep
.
inputId
.
path
.
contains
(
target
))
{
matches
=
true
;
break
;
}
}
if
(!
matches
)
{
return
;
}
log
.
info
(
'building for target
${buildStep.inputId.path}
'
);
await
bootstrapDdc
(
buildStep
,
platform:
flutterWebPlatform
);
}
}
/// A ddc-only entrypoint builder that respects the Flutter target flag.
class
FlutterWebEntrypointBuilder
implements
Builder
{
const
FlutterWebEntrypointBuilder
(
this
.
targets
,
this
.
release
);
final
List
<
String
>
targets
;
final
bool
release
;
@override
Map
<
String
,
List
<
String
>>
get
buildExtensions
=>
const
<
String
,
List
<
String
>>{
'.dart'
:
<
String
>[
ddcBootstrapExtension
,
jsEntrypointExtension
,
jsEntrypointSourceMapExtension
,
jsEntrypointArchiveExtension
,
digestsEntrypointExtension
,
],
};
@override
Future
<
void
>
build
(
BuildStep
buildStep
)
async
{
bool
matches
=
false
;
for
(
String
target
in
targets
)
{
if
(
buildStep
.
inputId
.
path
.
contains
(
fs
.
path
.
setExtension
(
target
,
'_web_entrypoint.dart'
)))
{
matches
=
true
;
break
;
}
}
if
(!
matches
)
{
return
;
}
log
.
info
(
'building for target
${buildStep.inputId.path}
'
);
if
(
release
)
{
await
bootstrapDart2Js
(
buildStep
);
}
else
{
await
bootstrapDdc
(
buildStep
,
platform:
flutterWebPlatform
);
}
}
}
/// Bootstraps the test entrypoint.
class
FlutterWebTestBootstrapBuilder
implements
Builder
{
const
FlutterWebTestBootstrapBuilder
();
@override
Map
<
String
,
List
<
String
>>
get
buildExtensions
=>
const
<
String
,
List
<
String
>>{
'_test.dart'
:
<
String
>[
'_test.dart.browser_test.dart'
,
]
};
@override
Future
<
void
>
build
(
BuildStep
buildStep
)
async
{
final
AssetId
id
=
buildStep
.
inputId
;
final
String
contents
=
await
buildStep
.
readAsString
(
id
);
final
String
assetPath
=
id
.
pathSegments
.
first
==
'lib'
?
path
.
url
.
join
(
'packages'
,
id
.
package
,
id
.
path
)
:
id
.
path
;
final
Metadata
metadata
=
parseMetadata
(
assetPath
,
contents
,
Runtime
.
builtIn
.
map
((
Runtime
runtime
)
=>
runtime
.
name
).
toSet
());
if
(
metadata
.
testOn
.
evaluate
(
SuitePlatform
(
Runtime
.
chrome
)))
{
await
buildStep
.
writeAsString
(
id
.
addExtension
(
'.browser_test.dart'
),
'''
import '
dart:
ui
' as ui;
import '
dart:
html
';
import '
dart:
js
';
import '
package:
stream_channel
/
stream_channel
.
dart
';
import '
package:
test_api
/
src
/
backend
/
stack_trace_formatter
.
dart
'; // ignore: implementation_imports
import '
package:
test_api
/
src
/
util
/
stack_trace_mapper
.
dart
'; // ignore: implementation_imports
import '
package:
test_api
/
src
/
remote_listener
.
dart
'; // ignore: implementation_imports
import '
package:
test_api
/
src
/
suite_channel_manager
.
dart
'; // ignore: implementation_imports
import "
${path.url.basename(id.path)}
" as test;
Future<void> main() async {
// Extra initialization for flutter_web.
// The following parameters are hard-coded in Flutter'
s
test
embedder
.
Since
// we don't have an embedder yet this is the lowest-most layer we can put
// this stuff in.
await
ui
.
webOnlyInitializeEngine
();
// TODO(flutterweb): remove need for dynamic cast.
(
ui
.
window
as
dynamic
).
debugOverrideDevicePixelRatio
(
3.0
);
(
ui
.
window
as
dynamic
).
webOnlyDebugPhysicalSizeOverride
=
const
ui
.
Size
(
2400
,
1800
);
internalBootstrapBrowserTest
(()
=>
test
.
main
);
}
void
internalBootstrapBrowserTest
(
Function
getMain
())
{
var
channel
=
serializeSuite
(
getMain
,
hidePrints:
false
,
beforeLoad:
()
async
{
var
serialized
=
await
suiteChannel
(
"test.browser.mapper"
).
stream
.
first
as
Map
;
if
(
serialized
==
null
)
return
;
});
postMessageChannel
().
pipe
(
channel
);
}
StreamChannel
serializeSuite
(
Function
getMain
(),
{
bool
hidePrints
=
true
,
Future
beforeLoad
()})
=>
RemoteListener
.
start
(
getMain
,
hidePrints:
hidePrints
,
beforeLoad:
beforeLoad
);
StreamChannel
suiteChannel
(
String
name
)
{
var
manager
=
SuiteChannelManager
.
current
;
if
(
manager
==
null
)
{
throw
StateError
(
'suiteChannel() may only be called within a test worker.'
);
}
return
manager
.
connectOut
(
name
);
}
StreamChannel
postMessageChannel
(
)
{
var
controller
=
StreamChannelController
(
sync:
true
);
window
.
onMessage
.
firstWhere
((
message
)
{
return
message
.
origin
==
window
.
location
.
origin
&&
message
.
data
==
"port"
;
}).
then
((
message
)
{
var
port
=
message
.
ports
.
first
;
var
portSubscription
=
port
.
onMessage
.
listen
((
message
)
{
controller
.
local
.
sink
.
add
(
message
.
data
);
});
controller
.
local
.
stream
.
listen
((
data
)
{
port
.
postMessage
({
"data"
:
data
});
},
onDone:
()
{
port
.
postMessage
({
"event"
:
"done"
});
portSubscription
.
cancel
();
});
});
context
[
'parent'
].
callMethod
(
'postMessage'
,
[
JsObject
.
jsify
({
"href"
:
window
.
location
.
href
,
"ready"
:
true
}),
window
.
location
.
origin
,
]);
return
controller
.
foreign
;
}
void
setStackTraceMapper
(
StackTraceMapper
mapper
)
{
var
formatter
=
StackTraceFormatter
.
current
;
if
(
formatter
==
null
)
{
throw
StateError
(
'setStackTraceMapper() may only be called within a test worker.'
);
}
formatter
.
configure
(
mapper:
mapper
);
}
''');
}
}
}
/// A shell builder which generates the web specific entrypoint.
class FlutterWebShellBuilder implements Builder {
const FlutterWebShellBuilder(this.targets);
final List<String> targets;
@override
FutureOr<void> build(BuildStep buildStep) async {
bool matches = false;
for (String target in targets) {
if (buildStep.inputId.path.contains(target)) {
matches = true;
break;
}
}
if (!matches) {
return;
}
final AssetId outputId = buildStep.inputId.changeExtension('
_web_entrypoint
.
dart
');
await buildStep.writeAsString(outputId, '''
import
'dart:ui'
as
ui
;
import
"
${path.url.basename(buildStep.inputId.path)}
"
as
entrypoint
;
Future
<
void
>
main
()
async
{
await
ui
.
webOnlyInitializePlatform
();
entrypoint
.
main
();
}
''');
}
@override
Map<String, List<String>> get buildExtensions => const <String, List<String>>{
'
.
dart
': <String>['
_web_entrypoint
.
dart
'],
};
}
Future<void> bootstrapDart2Js(BuildStep buildStep) async {
final AssetId dartEntrypointId = buildStep.inputId;
final AssetId moduleId = dartEntrypointId.changeExtension(moduleExtension(flutterWebPlatform));
final Module module = Module.fromJson(json.decode(await buildStep.readAsString(moduleId)));
final List<Module> allDeps = await module.computeTransitiveDependencies(buildStep, throwIfUnsupported: false)..add(module);
final ScratchSpace scratchSpace = await buildStep.fetchResource(scratchSpaceResource);
final Iterable<AssetId> allSrcs = allDeps.expand((Module module) => module.sources);
await scratchSpace.ensureAssets(allSrcs, buildStep);
final String packageFile = await _createPackageFile(allSrcs, buildStep, scratchSpace);
final String dartPath = dartEntrypointId.path.startsWith('
lib
/
')
? '
package:
$
{
dartEntrypointId
.
package
}/
'
'
$
{
dartEntrypointId
.
path
.
substring
(
'lib/'
.
length
)}
'
: dartEntrypointId.path;
final String jsOutputPath =
'
$
{
fs
.
path
.
withoutExtension
(
dartPath
.
replaceFirst
(
'package:'
,
'packages/'
))}
'
'
$jsEntrypointExtension
';
final String flutterWebSdkPath = artifacts.getArtifactPath(Artifact.flutterWebSdk);
final String librariesPath = fs.path.join(flutterWebSdkPath, '
libraries
.
json
');
final List<String> args = <String>[
'
--
libraries
-
spec
=
"
$librariesPath
"',
'
-
m
',
'
-
o4
',
'
-
o
',
'
$jsOutputPath
',
'
--
packages
=
"
$packageFile
"',
'
-
Ddart
.
vm
.
product
=
true
',
dartPath,
];
final Dart2JsBatchWorkerPool dart2js = await buildStep.fetchResource(dart2JsWorkerResource);
final Dart2JsResult result = await dart2js.compile(args);
final AssetId jsOutputId = dartEntrypointId.changeExtension(jsEntrypointExtension);
final io.File jsOutputFile = scratchSpace.fileFor(jsOutputId);
if (result.succeeded && jsOutputFile.existsSync()) {
log.info(result.output);
// Explicitly write out the original js file and sourcemap.
await scratchSpace.copyOutput(jsOutputId, buildStep);
final AssetId jsSourceMapId =
dartEntrypointId.changeExtension(jsEntrypointSourceMapExtension);
await _copyIfExists(jsSourceMapId, scratchSpace, buildStep);
} else {
log.severe(result.output);
}
}
Future<void> _copyIfExists(
AssetId id, ScratchSpace scratchSpace, AssetWriter writer) async {
final io.File file = scratchSpace.fileFor(id);
if (file.existsSync()) {
await scratchSpace.copyOutput(id, writer);
}
}
/// Creates a `.packages` file unique to this entrypoint at the root of the
/// scratch space and returns it'
s
filename
.
///
/// Since mulitple invocations of Dart2Js will share a scratch space and we only
/// know the set of packages involved the current entrypoint we can't construct
/// a `.packages` file that will work for all invocations of Dart2Js so a unique
/// file is created for every entrypoint that is run.
///
/// The filename is based off the MD5 hash of the asset path so that files are
/// unique regarless of situations like `web/foo/bar.dart` vs
/// `web/foo-bar.dart`.
Future
<
String
>
_createPackageFile
(
Iterable
<
AssetId
>
inputSources
,
BuildStep
buildStep
,
ScratchSpace
scratchSpace
)
async
{
final
Uri
inputUri
=
buildStep
.
inputId
.
uri
;
final
String
packageFileName
=
'.package-
${md5.convert(inputUri.toString().codeUnits)}
'
;
final
io
.
File
packagesFile
=
scratchSpace
.
fileFor
(
AssetId
(
buildStep
.
inputId
.
package
,
packageFileName
));
final
Set
<
String
>
packageNames
=
inputSources
.
map
((
AssetId
s
)
=>
s
.
package
).
toSet
();
final
String
packagesFileContent
=
packageNames
.
map
((
String
name
)
=>
'
$name
:packages/
$name
/'
).
join
(
'
\n
'
);
await
packagesFile
.
writeAsString
(
'# Generated for
$inputUri
\n
$packagesFileContent
'
);
return
packageFileName
;
}
packages/flutter_tools/lib/src/resident_web_runner.dart
View file @
7472fad1
...
...
@@ -131,8 +131,7 @@ class ResidentWebRunner extends ResidentRunner {
}
// Start the web compiler and build the assets.
await
webCompilationProxy
.
initialize
(
projectDirectory:
FlutterProject
.
current
().
directory
,
targets:
<
String
>[
target
],
projectDirectory:
flutterProject
.
directory
,
);
_lastCompiled
=
DateTime
.
now
();
final
AssetBundle
assetBundle
=
AssetBundleFactory
.
instance
.
createBundle
();
...
...
packages/flutter_tools/lib/src/test/runner.dart
View file @
7472fad1
...
...
@@ -76,9 +76,6 @@ Future<int> runTests(
final
bool
result
=
await
webCompilationProxy
.
initialize
(
projectDirectory:
flutterProject
.
directory
,
testOutputDir:
tempBuildDir
,
targets:
testFiles
.
map
((
String
testFile
)
{
return
fs
.
path
.
relative
(
testFile
,
from:
flutterProject
.
directory
.
path
);
}).
toList
(),
);
if
(!
result
)
{
throwToolExit
(
'Failed to compile tests'
);
...
...
packages/flutter_tools/lib/src/web/compile.dart
View file @
7472fad1
...
...
@@ -30,7 +30,6 @@ Future<void> buildWeb(FlutterProject flutterProject, String target, BuildInfo bu
try
{
result
=
await
webCompilationProxy
.
initialize
(
projectDirectory:
FlutterProject
.
current
().
directory
,
targets:
<
String
>[
target
],
release:
buildInfo
.
isRelease
,
);
if
(
result
)
{
...
...
@@ -79,11 +78,8 @@ class WebCompilationProxy {
///
/// `release` controls whether we build the bundle for dartdevc or only
/// the entrypoints for dart2js to later take over.
///
/// `targets` controls the specific compiler targets.
Future
<
bool
>
initialize
({
@required
Directory
projectDirectory
,
@required
List
<
String
>
targets
,
String
testOutputDir
,
bool
release
,
})
async
{
...
...
packages/flutter_tools/test/commands/build_web_test.dart
View file @
7472fad1
...
...
@@ -38,7 +38,6 @@ void main() {
fs
.
file
(
fs
.
path
.
join
(
'lib'
,
'main.dart'
)).
createSync
(
recursive:
true
);
when
(
mockWebCompilationProxy
.
initialize
(
projectDirectory:
anyNamed
(
'projectDirectory'
),
targets:
anyNamed
(
'targets'
),
release:
anyNamed
(
'release'
)
)).
thenAnswer
((
Invocation
invocation
)
{
final
String
path
=
fs
.
path
.
join
(
'.dart_tool'
,
'build'
,
'flutter_web'
,
'foo'
,
'lib'
,
'main_web_entrypoint.dart.js'
);
...
...
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