From f605460bf4781608daca56fe761c39da937decc7 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Mon, 26 Jun 2023 11:46:13 -0700 Subject: [PATCH 1/8] Run instance tests with frontend server --- dwds/test/fixtures/context.dart | 14 +- dwds/test/instances/instance_test.dart | 600 ++++++++++-------- .../lib/src/asset_server.dart | 4 +- frontend_server_common/lib/src/devfs.dart | 14 +- 4 files changed, 340 insertions(+), 292 deletions(-) diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index fe010249d..837d61591 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -211,6 +211,7 @@ class TestContext { Stream buildResults; RequireStrategy requireStrategy; String basePath = ''; + String index = project.filePathToServe; _port = await findUnusedPort(); switch (compilationMode) { @@ -279,7 +280,12 @@ class TestContext { break; case CompilationMode.frontendServer: { - _logger.info('Index: ${project.filePathToServe}'); + index = webCompatiblePath([ + project.directoryToServe, + project.filePathToServe, + ]); + + _logger.info('Index: $index'); final entry = p.toUri( p.join(project.webAssetsPath, project.dartEntryFileName), @@ -311,7 +317,7 @@ class TestContext { fileSystem, hostname, assetServerPort, - p.join(project.directoryToServe, project.filePathToServe), + index, ); if (enableExpressionEvaluation) { @@ -393,8 +399,8 @@ class TestContext { ); _appUrl = basePath.isEmpty - ? 'http://localhost:$port/${project.filePathToServe}' - : 'http://localhost:$port/$basePath/${project.filePathToServe}'; + ? 'http://localhost:$port/$index' + : 'http://localhost:$port/$basePath/$index'; if (launchChrome) { await _webDriver?.get(appUrl); diff --git a/dwds/test/instances/instance_test.dart b/dwds/test/instances/instance_test.dart index 7c440529f..6a37ee94d 100644 --- a/dwds/test/instances/instance_test.dart +++ b/dwds/test/instances/instance_test.dart @@ -19,301 +19,337 @@ import '../fixtures/project.dart'; void main() { // Enable verbose logging for debugging. final debug = false; - final provider = TestSdkConfigurationProvider(); + + final provider = TestSdkConfigurationProvider(verbose: debug); tearDownAll(provider.dispose); + for (var compilationMode in CompilationMode.values) { + _runTests( + provider: provider, + compilationMode: compilationMode, + debug: debug, + ); + } +} + +void _runTests({ + required TestSdkConfigurationProvider provider, + required CompilationMode compilationMode, + required bool debug, +}) { final context = TestContext(TestProject.testScopesWithSoundNullSafety, provider); late AppInspector inspector; - setUpAll(() async { - setCurrentLogWriter(debug: debug); - await context.setUp(); - final chromeProxyService = context.service; - inspector = chromeProxyService.inspector; - }); - - tearDownAll(() async { - await context.tearDown(); - }); - - final url = 'org-dartlang-app:///example/scopes/main.dart'; - - String libraryVariableExpression(String variable) => - '${globalLoadStrategy.loadModuleSnippet}("dart_sdk").dart.getModuleLibraries("example/scopes/main")' - '["$url"]["$variable"];'; - - String interceptorsNewExpression(String type) => - "require('dart_sdk')._interceptors.$type['_#new#tearOff']()"; - - /// A reference to the the variable `libraryPublicFinal`, an instance of - /// `MyTestClass`. - Future libraryPublicFinal() => - inspector.jsEvaluate(libraryVariableExpression('libraryPublicFinal')); - - /// A reference to the the variable `libraryPublic`, a List of Strings. - Future libraryPublic() => - inspector.jsEvaluate(libraryVariableExpression('libraryPublic')); - - group('instanceRef', () { - setUp(() => setCurrentLogWriter(debug: debug)); - - test('for a null', () async { - final remoteObject = await libraryPublicFinal(); - final nullVariable = await inspector.loadField(remoteObject, 'notFinal'); - final ref = await inspector.instanceRefFor(nullVariable); - expect(ref!.valueAsString, 'null'); - expect(ref.kind, InstanceKind.kNull); - final classRef = ref.classRef!; - expect(classRef.name, 'Null'); - expect(classRef.id, 'classes|dart:core|Null'); - expect(inspector.isDisplayableObject(ref), isTrue); - }); - - test('for a double', () async { - final remoteObject = await libraryPublicFinal(); - final count = await inspector.loadField(remoteObject, 'count'); - final ref = await inspector.instanceRefFor(count); - expect(ref!.valueAsString, '0'); - expect(ref.kind, InstanceKind.kDouble); - final classRef = ref.classRef!; - expect(classRef.name, 'Double'); - expect(classRef.id, 'classes|dart:core|Double'); - expect(inspector.isDisplayableObject(ref), isTrue); - }); - - test('for a class', () async { - final remoteObject = await libraryPublicFinal(); - final count = await inspector.loadField(remoteObject, 'myselfField'); - final ref = await inspector.instanceRefFor(count); - expect(ref!.kind, InstanceKind.kPlainInstance); - final classRef = ref.classRef!; - expect(classRef.name, 'MyTestClass'); - expect( - classRef.id, - 'classes|org-dartlang-app:///example/scopes/main.dart' - '|MyTestClass'); - expect(inspector.isDisplayableObject(ref), isTrue); - }); - - test('for closure', () async { - final remoteObject = await libraryPublicFinal(); - final properties = await inspector.getProperties(remoteObject.objectId!); - final closure = - properties.firstWhere((property) => property.name == 'closure'); - final ref = await inspector.instanceRefFor(closure.value!); - final functionName = ref!.closureFunction!.name; - // Older SDKs do not contain function names - if (functionName != 'Closure') { - expect(functionName, 'someFunction'); - } - expect(ref.kind, InstanceKind.kClosure); - expect(inspector.isDisplayableObject(ref), isTrue); - }); - - test('for a list', () async { - final remoteObject = await libraryPublic(); - final ref = await inspector.instanceRefFor(remoteObject); - expect(ref!.length, greaterThan(0)); - expect(ref.kind, InstanceKind.kList); - expect(ref.classRef!.name, 'List'); - expect(inspector.isDisplayableObject(ref), isTrue); - }); - - test('for map', () async { - final remoteObject = - await inspector.jsEvaluate(libraryVariableExpression('map')); - final ref = await inspector.instanceRefFor(remoteObject); - expect(ref!.length, 2); - expect(ref.kind, InstanceKind.kMap); - expect(ref.classRef!.name, 'LinkedMap'); - expect(inspector.isDisplayableObject(ref), isTrue); - }); - - test('for an IdentityMap', () async { - final remoteObject = - await inspector.jsEvaluate(libraryVariableExpression('identityMap')); - final ref = await inspector.instanceRefFor(remoteObject); - expect(ref!.length, 2); - expect(ref.kind, InstanceKind.kMap); - expect(ref.classRef!.name, 'IdentityMap'); - expect(inspector.isDisplayableObject(ref), isTrue); - }); - - test('for a native JavaScript error', () async { - final remoteObject = - await inspector.jsEvaluate(interceptorsNewExpression('NativeError')); - final ref = await inspector.instanceRefFor(remoteObject); - expect(ref!.kind, InstanceKind.kPlainInstance); - expect(ref.classRef!.name, 'NativeError'); - expect(inspector.isDisplayableObject(ref), isFalse); - expect(inspector.isNativeJsError(ref), isTrue); - expect(inspector.isNativeJsObject(ref), isFalse); - }); - - test('for a native JavaScript type error', () async { - final remoteObject = await inspector - .jsEvaluate(interceptorsNewExpression('JSNoSuchMethodError')); - final ref = await inspector.instanceRefFor(remoteObject); - expect(ref!.kind, InstanceKind.kPlainInstance); - expect(ref.classRef!.name, 'JSNoSuchMethodError'); - expect(inspector.isDisplayableObject(ref), isFalse); - expect(inspector.isNativeJsError(ref), isTrue); - expect(inspector.isNativeJsObject(ref), isFalse); - }); - - test('for a native JavaScript object', () async { - final remoteObject = await inspector - .jsEvaluate(interceptorsNewExpression('LegacyJavaScriptObject')); - final ref = await inspector.instanceRefFor(remoteObject); - expect(ref!.kind, InstanceKind.kPlainInstance); - expect(ref.classRef!.name, 'LegacyJavaScriptObject'); - expect(inspector.isDisplayableObject(ref), isFalse); - expect(inspector.isNativeJsError(ref), isFalse); - expect(inspector.isNativeJsObject(ref), isTrue); - }); - }); - - group('instance', () { - setUp(() => setCurrentLogWriter(debug: debug)); - test('for class object', () async { - final remoteObject = await libraryPublicFinal(); - final instance = await inspector.instanceFor(remoteObject); - expect(instance!.kind, InstanceKind.kPlainInstance); - final classRef = instance.classRef!; - expect(classRef, isNotNull); - expect(classRef.name, 'MyTestClass'); - final boundFieldNames = - instance.fields!.map((boundField) => boundField.decl!.name).toList(); - expect(boundFieldNames, [ - '_privateField', - 'abstractField', - 'closure', - 'count', - 'message', - 'myselfField', - 'notFinal', - 'tornOff', - ]); - final fieldNames = - instance.fields!.map((boundField) => boundField.name).toList(); - expect(boundFieldNames, fieldNames); - for (var field in instance.fields!) { - expect(field.name, isNotNull); - expect(field.decl!.declaredType, isNotNull); - } - expect(inspector.isDisplayableObject(instance), isTrue); - }); - - test('for closure', () async { - final remoteObject = await libraryPublicFinal(); - final properties = await inspector.getProperties(remoteObject.objectId!); - final closure = - properties.firstWhere((property) => property.name == 'closure'); - final instance = await inspector.instanceFor(closure.value!); - expect(instance!.kind, InstanceKind.kClosure); - expect(instance.classRef!.name, 'Closure'); - expect(inspector.isDisplayableObject(instance), isTrue); - }); - - test('for a nested class', () async { - final libraryRemoteObject = await libraryPublicFinal(); - final fieldRemoteObject = - await inspector.loadField(libraryRemoteObject, 'myselfField'); - final instance = await inspector.instanceFor(fieldRemoteObject); - expect(instance!.kind, InstanceKind.kPlainInstance); - final classRef = instance.classRef!; - expect(classRef, isNotNull); - expect(classRef.name, 'MyTestClass'); - expect(inspector.isDisplayableObject(instance), isTrue); - }); - - test('for a list', () async { - final remote = await libraryPublic(); - final instance = await inspector.instanceFor(remote); - expect(instance!.kind, InstanceKind.kList); - final classRef = instance.classRef!; - expect(classRef, isNotNull); - expect(classRef.name, 'List'); - final first = instance.elements![0]; - expect(first.valueAsString, 'library'); - expect(inspector.isDisplayableObject(instance), isTrue); - }); - - test('for a map', () async { - final remote = - await inspector.jsEvaluate(libraryVariableExpression('map')); - final instance = await inspector.instanceFor(remote); - expect(instance!.kind, InstanceKind.kMap); - final classRef = instance.classRef!; - expect(classRef.name, 'LinkedMap'); - final first = instance.associations![0].value as InstanceRef; - expect(first.kind, InstanceKind.kList); - expect(first.length, 3); - final second = instance.associations![1].value as InstanceRef; - expect(second.kind, InstanceKind.kString); - expect(second.valueAsString, 'something'); - expect(inspector.isDisplayableObject(instance), isTrue); - }); - - test('for an identityMap', () async { - final remote = - await inspector.jsEvaluate(libraryVariableExpression('identityMap')); - final instance = await inspector.instanceFor(remote); - expect(instance!.kind, InstanceKind.kMap); - final classRef = instance.classRef!; - expect(classRef.name, 'IdentityMap'); - final first = instance.associations![0].value; - expect(first.valueAsString, '1'); - expect(inspector.isDisplayableObject(instance), isTrue); - }); - - test('for a class that implements List', () async { - // The VM only uses kind List for SDK lists, and we follow that. - final remote = - await inspector.jsEvaluate(libraryVariableExpression('notAList')); - final instance = await inspector.instanceFor(remote); - expect(instance!.kind, InstanceKind.kPlainInstance); - final classRef = instance.classRef!; - expect(classRef.name, 'NotReallyAList'); - expect(instance.elements, isNull); - final field = instance.fields!.first; - expect(field.decl!.name, '_internal'); - expect(inspector.isDisplayableObject(instance), isTrue); + group('$compilationMode |', () { + setUpAll(() async { + setCurrentLogWriter(debug: debug); + await context.setUp(compilationMode: compilationMode); + final chromeProxyService = context.service; + inspector = chromeProxyService.inspector; }); - test('for a native JavaScript error', () async { - final remoteObject = - await inspector.jsEvaluate(interceptorsNewExpression('NativeError')); - final instance = await inspector.instanceFor(remoteObject); - expect(instance!.kind, InstanceKind.kPlainInstance); - expect(instance.classRef!.name, 'NativeError'); - expect(inspector.isDisplayableObject(instance), isFalse); - expect(inspector.isNativeJsError(instance), isTrue); - expect(inspector.isNativeJsObject(instance), isFalse); + tearDownAll(() async { + await context.tearDown(); }); - test('for a native JavaScript type error', () async { - final remoteObject = await inspector - .jsEvaluate(interceptorsNewExpression('JSNoSuchMethodError')); - final instance = await inspector.instanceFor(remoteObject); - expect(instance!.kind, InstanceKind.kPlainInstance); - expect(instance.classRef!.name, 'JSNoSuchMethodError'); - expect(inspector.isDisplayableObject(instance), isFalse); - expect(inspector.isNativeJsError(instance), isTrue); - expect(inspector.isNativeJsObject(instance), isFalse); + final url = 'org-dartlang-app:///example/scopes/main.dart'; + + String libraryName(CompilationMode compilationMode) => + compilationMode == CompilationMode.frontendServer + ? "example/scopes/main.dart" + : "example/scopes/main"; + + String libraryVariableExpression( + String variable, + CompilationMode compilationMode, + ) => + '${globalLoadStrategy.loadModuleSnippet}("dart_sdk").dart.' + 'getModuleLibraries("${libraryName(compilationMode)}")' + '["$url"]["$variable"];'; + + String interceptorsNewExpression(String type) => + "require('dart_sdk')._interceptors.$type['_#new#tearOff']()"; + + /// A reference to the the variable `libraryPublicFinal`, an instance of + /// `MyTestClass`. + Future libraryPublicFinal(CompilationMode compilationMode) => + inspector.jsEvaluate( + libraryVariableExpression('libraryPublicFinal', compilationMode), + ); + + /// A reference to the the variable `libraryPublic`, a List of Strings. + Future libraryPublic(CompilationMode compilationMode) => + inspector.jsEvaluate( + libraryVariableExpression('libraryPublic', compilationMode), + ); + + group('instanceRef', () { + setUp(() => setCurrentLogWriter(debug: debug)); + + test('for a null', () async { + final remoteObject = await libraryPublicFinal(compilationMode); + final nullVariable = + await inspector.loadField(remoteObject, 'notFinal'); + final ref = await inspector.instanceRefFor(nullVariable); + expect(ref!.valueAsString, 'null'); + expect(ref.kind, InstanceKind.kNull); + final classRef = ref.classRef!; + expect(classRef.name, 'Null'); + expect(classRef.id, 'classes|dart:core|Null'); + expect(inspector.isDisplayableObject(ref), isTrue); + }); + + test('for a double', () async { + final remoteObject = await libraryPublicFinal(compilationMode); + final count = await inspector.loadField(remoteObject, 'count'); + final ref = await inspector.instanceRefFor(count); + expect(ref!.valueAsString, '0'); + expect(ref.kind, InstanceKind.kDouble); + final classRef = ref.classRef!; + expect(classRef.name, 'Double'); + expect(classRef.id, 'classes|dart:core|Double'); + expect(inspector.isDisplayableObject(ref), isTrue); + }); + + test('for a class', () async { + final remoteObject = await libraryPublicFinal(compilationMode); + final count = await inspector.loadField(remoteObject, 'myselfField'); + final ref = await inspector.instanceRefFor(count); + expect(ref!.kind, InstanceKind.kPlainInstance); + final classRef = ref.classRef!; + expect(classRef.name, 'MyTestClass'); + expect( + classRef.id, + 'classes|org-dartlang-app:///example/scopes/main.dart' + '|MyTestClass'); + expect(inspector.isDisplayableObject(ref), isTrue); + }); + + test('for closure', () async { + final remoteObject = await libraryPublicFinal(compilationMode); + final properties = + await inspector.getProperties(remoteObject.objectId!); + final closure = + properties.firstWhere((property) => property.name == 'closure'); + final ref = await inspector.instanceRefFor(closure.value!); + final functionName = ref!.closureFunction!.name; + // Older SDKs do not contain function names + if (functionName != 'Closure') { + expect(functionName, 'someFunction'); + } + expect(ref.kind, InstanceKind.kClosure); + expect(inspector.isDisplayableObject(ref), isTrue); + }); + + test('for a list', () async { + final remoteObject = await libraryPublic(compilationMode); + final ref = await inspector.instanceRefFor(remoteObject); + expect(ref!.length, greaterThan(0)); + expect(ref.kind, InstanceKind.kList); + expect(ref.classRef!.name, 'List'); + expect(inspector.isDisplayableObject(ref), isTrue); + }); + + test('for map', () async { + final remoteObject = await inspector + .jsEvaluate(libraryVariableExpression('map', compilationMode)); + final ref = await inspector.instanceRefFor(remoteObject); + expect(ref!.length, 2); + expect(ref.kind, InstanceKind.kMap); + expect(ref.classRef!.name, 'LinkedMap'); + expect(inspector.isDisplayableObject(ref), isTrue); + }); + + test('for an IdentityMap', () async { + final remoteObject = await inspector.jsEvaluate( + libraryVariableExpression('identityMap', compilationMode), + ); + final ref = await inspector.instanceRefFor(remoteObject); + expect(ref!.length, 2); + expect(ref.kind, InstanceKind.kMap); + expect(ref.classRef!.name, 'IdentityMap'); + expect(inspector.isDisplayableObject(ref), isTrue); + }); + + test('for a native JavaScript error', () async { + final remoteObject = await inspector + .jsEvaluate(interceptorsNewExpression('NativeError')); + final ref = await inspector.instanceRefFor(remoteObject); + expect(ref!.kind, InstanceKind.kPlainInstance); + expect(ref.classRef!.name, 'NativeError'); + expect(inspector.isDisplayableObject(ref), isFalse); + expect(inspector.isNativeJsError(ref), isTrue); + expect(inspector.isNativeJsObject(ref), isFalse); + }); + + test('for a native JavaScript type error', () async { + final remoteObject = await inspector + .jsEvaluate(interceptorsNewExpression('JSNoSuchMethodError')); + final ref = await inspector.instanceRefFor(remoteObject); + expect(ref!.kind, InstanceKind.kPlainInstance); + expect(ref.classRef!.name, 'JSNoSuchMethodError'); + expect(inspector.isDisplayableObject(ref), isFalse); + expect(inspector.isNativeJsError(ref), isTrue); + expect(inspector.isNativeJsObject(ref), isFalse); + }); + + test('for a native JavaScript object', () async { + final remoteObject = await inspector + .jsEvaluate(interceptorsNewExpression('LegacyJavaScriptObject')); + final ref = await inspector.instanceRefFor(remoteObject); + expect(ref!.kind, InstanceKind.kPlainInstance); + expect(ref.classRef!.name, 'LegacyJavaScriptObject'); + expect(inspector.isDisplayableObject(ref), isFalse); + expect(inspector.isNativeJsError(ref), isFalse); + expect(inspector.isNativeJsObject(ref), isTrue); + }); }); - test('for a native JavaScript object', () async { - final remoteObject = await inspector - .jsEvaluate(interceptorsNewExpression('LegacyJavaScriptObject')); - final instance = await inspector.instanceFor(remoteObject); - expect(instance!.kind, InstanceKind.kPlainInstance); - expect(instance.classRef!.name, 'LegacyJavaScriptObject'); - expect(inspector.isDisplayableObject(instance), isFalse); - expect(inspector.isNativeJsError(instance), isFalse); - expect(inspector.isNativeJsObject(instance), isTrue); + group('instance', () { + setUp(() => setCurrentLogWriter(debug: debug)); + test('for class object', () async { + final remoteObject = await libraryPublicFinal(compilationMode); + final instance = await inspector.instanceFor(remoteObject); + expect(instance!.kind, InstanceKind.kPlainInstance); + final classRef = instance.classRef!; + expect(classRef, isNotNull); + expect(classRef.name, 'MyTestClass'); + final boundFieldNames = instance.fields! + .map((boundField) => boundField.decl!.name) + .toList(); + expect(boundFieldNames, [ + '_privateField', + 'abstractField', + 'closure', + 'count', + 'message', + 'myselfField', + 'notFinal', + 'tornOff', + ]); + final fieldNames = + instance.fields!.map((boundField) => boundField.name).toList(); + expect(boundFieldNames, fieldNames); + for (var field in instance.fields!) { + expect(field.name, isNotNull); + expect(field.decl!.declaredType, isNotNull); + } + expect(inspector.isDisplayableObject(instance), isTrue); + }); + + test('for closure', () async { + final remoteObject = await libraryPublicFinal(compilationMode); + final properties = + await inspector.getProperties(remoteObject.objectId!); + final closure = + properties.firstWhere((property) => property.name == 'closure'); + final instance = await inspector.instanceFor(closure.value!); + expect(instance!.kind, InstanceKind.kClosure); + expect(instance.classRef!.name, 'Closure'); + expect(inspector.isDisplayableObject(instance), isTrue); + }); + + test('for a nested class', () async { + final libraryRemoteObject = await libraryPublicFinal(compilationMode); + final fieldRemoteObject = + await inspector.loadField(libraryRemoteObject, 'myselfField'); + final instance = await inspector.instanceFor(fieldRemoteObject); + expect(instance!.kind, InstanceKind.kPlainInstance); + final classRef = instance.classRef!; + expect(classRef, isNotNull); + expect(classRef.name, 'MyTestClass'); + expect(inspector.isDisplayableObject(instance), isTrue); + }); + + test('for a list', () async { + final remote = await libraryPublic(compilationMode); + final instance = await inspector.instanceFor(remote); + expect(instance!.kind, InstanceKind.kList); + final classRef = instance.classRef!; + expect(classRef, isNotNull); + expect(classRef.name, 'List'); + final first = instance.elements![0]; + expect(first.valueAsString, 'library'); + expect(inspector.isDisplayableObject(instance), isTrue); + }); + + test('for a map', () async { + final remote = await inspector + .jsEvaluate(libraryVariableExpression('map', compilationMode)); + final instance = await inspector.instanceFor(remote); + expect(instance!.kind, InstanceKind.kMap); + final classRef = instance.classRef!; + expect(classRef.name, 'LinkedMap'); + final first = instance.associations![0].value as InstanceRef; + expect(first.kind, InstanceKind.kList); + expect(first.length, 3); + final second = instance.associations![1].value as InstanceRef; + expect(second.kind, InstanceKind.kString); + expect(second.valueAsString, 'something'); + expect(inspector.isDisplayableObject(instance), isTrue); + }); + + test('for an identityMap', () async { + final remote = await inspector.jsEvaluate( + libraryVariableExpression('identityMap', compilationMode), + ); + final instance = await inspector.instanceFor(remote); + expect(instance!.kind, InstanceKind.kMap); + final classRef = instance.classRef!; + expect(classRef.name, 'IdentityMap'); + final first = instance.associations![0].value; + expect(first.valueAsString, '1'); + expect(inspector.isDisplayableObject(instance), isTrue); + }); + + test('for a class that implements List', () async { + // The VM only uses kind List for SDK lists, and we follow that. + final remote = await inspector + .jsEvaluate(libraryVariableExpression('notAList', compilationMode)); + final instance = await inspector.instanceFor(remote); + expect(instance!.kind, InstanceKind.kPlainInstance); + final classRef = instance.classRef!; + expect(classRef.name, 'NotReallyAList'); + expect(instance.elements, isNull); + final field = instance.fields!.first; + expect(field.decl!.name, '_internal'); + expect(inspector.isDisplayableObject(instance), isTrue); + }); + + test('for a native JavaScript error', () async { + final remoteObject = await inspector + .jsEvaluate(interceptorsNewExpression('NativeError')); + final instance = await inspector.instanceFor(remoteObject); + expect(instance!.kind, InstanceKind.kPlainInstance); + expect(instance.classRef!.name, 'NativeError'); + expect(inspector.isDisplayableObject(instance), isFalse); + expect(inspector.isNativeJsError(instance), isTrue); + expect(inspector.isNativeJsObject(instance), isFalse); + }); + + test('for a native JavaScript type error', () async { + final remoteObject = await inspector + .jsEvaluate(interceptorsNewExpression('JSNoSuchMethodError')); + final instance = await inspector.instanceFor(remoteObject); + expect(instance!.kind, InstanceKind.kPlainInstance); + expect(instance.classRef!.name, 'JSNoSuchMethodError'); + expect(inspector.isDisplayableObject(instance), isFalse); + expect(inspector.isNativeJsError(instance), isTrue); + expect(inspector.isNativeJsObject(instance), isFalse); + }); + + test('for a native JavaScript object', () async { + final remoteObject = await inspector + .jsEvaluate(interceptorsNewExpression('LegacyJavaScriptObject')); + final instance = await inspector.instanceFor(remoteObject); + expect(instance!.kind, InstanceKind.kPlainInstance); + expect(instance.classRef!.name, 'LegacyJavaScriptObject'); + expect(inspector.isDisplayableObject(instance), isFalse); + expect(inspector.isNativeJsError(instance), isFalse); + expect(inspector.isNativeJsObject(instance), isTrue); + }); }); }); } diff --git a/frontend_server_common/lib/src/asset_server.dart b/frontend_server_common/lib/src/asset_server.dart index 2731d1d30..0968ca145 100644 --- a/frontend_server_common/lib/src/asset_server.dart +++ b/frontend_server_common/lib/src/asset_server.dart @@ -90,7 +90,9 @@ class TestAssetServer implements AssetReader { var headers = {}; - if (request.url.path.endsWith('index.html')) { + if (request.url.path.endsWith('.html')) { + print('Index request: ${request.url.path}'); + print('Index path: $index'); var indexFile = _fileSystem.file(index); if (indexFile.existsSync()) { headers[HttpHeaders.contentTypeHeader] = 'text/html'; diff --git a/frontend_server_common/lib/src/devfs.dart b/frontend_server_common/lib/src/devfs.dart index 1c1c71db5..de31230a1 100644 --- a/frontend_server_common/lib/src/devfs.dart +++ b/frontend_server_common/lib/src/devfs.dart @@ -62,14 +62,18 @@ class WebDevFS { final mainPath = mainUri.toFilePath(); final outputDirectoryPath = fileSystem.file(mainPath).parent.path; final entryPoint = mainUri.toString(); + final directory = p.dirname(entryPoint); + final require = p.join(directory, 'require.js'); + final stackMapper = p.join(directory, 'stack_trace_mapper.js'); + final main = p.join(directory, 'main.dart.js'); + final bootstrap = p.join(directory, 'main_module.bootstrap.js'); assetServer.writeFile( entryPoint, fileSystem.file(mainPath).readAsStringSync()); - assetServer.writeFile('require.js', requireJS.readAsStringSync()); + assetServer.writeFile(require, requireJS.readAsStringSync()); + assetServer.writeFile(stackMapper, stackTraceMapper.readAsStringSync()); assetServer.writeFile( - 'stack_trace_mapper.js', stackTraceMapper.readAsStringSync()); - assetServer.writeFile( - 'main.dart.js', + main, generateBootstrapScript( requireUrl: 'require.js', mapperUrl: 'stack_trace_mapper.js', @@ -77,7 +81,7 @@ class WebDevFS { ), ); assetServer.writeFile( - 'main_module.bootstrap.js', + bootstrap, generateMainModule( entrypoint: entryPoint, ), From 054ee50155b1970af74f686ef1fe585ea6227ea3 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Mon, 26 Jun 2023 13:26:57 -0700 Subject: [PATCH 2/8] Cleanup --- frontend_server_common/lib/src/asset_server.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend_server_common/lib/src/asset_server.dart b/frontend_server_common/lib/src/asset_server.dart index 0968ca145..fde1315bb 100644 --- a/frontend_server_common/lib/src/asset_server.dart +++ b/frontend_server_common/lib/src/asset_server.dart @@ -91,8 +91,6 @@ class TestAssetServer implements AssetReader { var headers = {}; if (request.url.path.endsWith('.html')) { - print('Index request: ${request.url.path}'); - print('Index path: $index'); var indexFile = _fileSystem.file(index); if (indexFile.existsSync()) { headers[HttpHeaders.contentTypeHeader] = 'text/html'; From 48adf44318f71b78931a33fbe5157af61a454088 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Tue, 27 Jun 2023 09:57:56 -0700 Subject: [PATCH 3/8] Try fixing tests --- dwds/test/evaluate_common.dart | 2 +- dwds/test/fixtures/context.dart | 8 +++++++- dwds/test/instances/instance_test.dart | 4 ++-- .../lib/src/asset_server.dart | 17 ++++++++++++++--- frontend_server_common/lib/src/devfs.dart | 6 ++++++ 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/dwds/test/evaluate_common.dart b/dwds/test/evaluate_common.dart index f8aa7b728..a4dfaa8fd 100644 --- a/dwds/test/evaluate_common.dart +++ b/dwds/test/evaluate_common.dart @@ -494,7 +494,7 @@ void testAll({ expect(result, matchInstanceRef('23')); }); - }); + }, solo: true); test('evaluate expression in a class constructor in a library', () async { diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index 837d61591..1ad175f01 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -285,7 +285,12 @@ class TestContext { project.filePathToServe, ]); - _logger.info('Index: $index'); + print('Directory: ${project.directoryToServe}'); + print('Index: ${project.filePathToServe}'); + + //index = project.filePathToServe; + + print('Context Index: $index'); final entry = p.toUri( p.join(project.webAssetsPath, project.dartEntryFileName), @@ -318,6 +323,7 @@ class TestContext { hostname, assetServerPort, index, + //p.join(project.directoryToServe, project.filePathToServe), ); if (enableExpressionEvaluation) { diff --git a/dwds/test/instances/instance_test.dart b/dwds/test/instances/instance_test.dart index 6a37ee94d..a74cc9667 100644 --- a/dwds/test/instances/instance_test.dart +++ b/dwds/test/instances/instance_test.dart @@ -23,7 +23,7 @@ void main() { final provider = TestSdkConfigurationProvider(verbose: debug); tearDownAll(provider.dispose); - for (var compilationMode in CompilationMode.values) { + for (var compilationMode in [CompilationMode.frontendServer]) { _runTests( provider: provider, compilationMode: compilationMode, @@ -99,7 +99,7 @@ void _runTests({ expect(classRef.name, 'Null'); expect(classRef.id, 'classes|dart:core|Null'); expect(inspector.isDisplayableObject(ref), isTrue); - }); + }, solo: true); test('for a double', () async { final remoteObject = await libraryPublicFinal(compilationMode); diff --git a/frontend_server_common/lib/src/asset_server.dart b/frontend_server_common/lib/src/asset_server.dart index fde1315bb..ad8074d19 100644 --- a/frontend_server_common/lib/src/asset_server.dart +++ b/frontend_server_common/lib/src/asset_server.dart @@ -13,6 +13,7 @@ import 'package:dwds/asset_reader.dart'; import 'package:file/file.dart'; import 'package:logging/logging.dart'; import 'package:mime/mime.dart' as mime; +import 'package:path/path.dart' as p; import 'package:shelf/shelf.dart' as shelf; import 'package:test_common/test_sdk_layout.dart'; @@ -43,7 +44,11 @@ class TestAssetServer implements AssetReader { this._fileSystem, this._sdkLayout, ) { - basePath = _parseBasePathFromIndexHtml(index); + // Base from index file replaces the base path in main.dart.js + // and everything that is loaded from there. + final baseFromIndex = _parseBasePathFromIndexHtml(index); + basePath = baseFromIndex.isNotEmpty ? baseFromIndex : p.dirname(index); + print('BASE PATH: $basePath'); } bool hasFile(String path) => _files.containsKey(path); @@ -82,11 +87,12 @@ class TestAssetServer implements AssetReader { // Assets are served via GET only. return shelf.Response.notFound(''); } - + print('Request: ${request.url.path}'); final requestPath = _stripBasePath(request.url.path, basePath); if (requestPath == null) { return shelf.Response.notFound(''); } + print('Stripped request: $requestPath'); var headers = {}; @@ -246,7 +252,12 @@ class TestAssetServer implements AssetReader { return dartFile; } - final segments = path.split('/'); + var segments = path.split('/'); + if (segments.contains('packages')) { + segments = segments.skipWhile((value) => value != 'packages').toList(); + path = segments.join('/'); + } + print('Segments: $segments'); // The file might have been a package file which is signaled by a // `/packages//` request. diff --git a/frontend_server_common/lib/src/devfs.dart b/frontend_server_common/lib/src/devfs.dart index de31230a1..100e23e29 100644 --- a/frontend_server_common/lib/src/devfs.dart +++ b/frontend_server_common/lib/src/devfs.dart @@ -62,12 +62,18 @@ class WebDevFS { final mainPath = mainUri.toFilePath(); final outputDirectoryPath = fileSystem.file(mainPath).parent.path; final entryPoint = mainUri.toString(); + print('Entrypoint: $entryPoint'); final directory = p.dirname(entryPoint); final require = p.join(directory, 'require.js'); final stackMapper = p.join(directory, 'stack_trace_mapper.js'); final main = p.join(directory, 'main.dart.js'); final bootstrap = p.join(directory, 'main_module.bootstrap.js'); + // final require = 'require.js'; + // final stackMapper = 'stack_trace_mapper.js'; + // final main = 'main.dart.js'; + // final bootstrap = 'main_module.bootstrap.js'; + assetServer.writeFile( entryPoint, fileSystem.file(mainPath).readAsStringSync()); assetServer.writeFile(require, requireJS.readAsStringSync()); From 415f6c6edcc1196a52a1eba0e7031226aab694ef Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 28 Jun 2023 12:34:48 -0700 Subject: [PATCH 4/8] Addressed CR comments and fixed failing tests --- dwds/CHANGELOG.md | 4 ++- dwds/lib/dart_web_debug_service.dart | 2 ++ dwds/lib/src/handlers/dev_handler.dart | 7 +++-- dwds/lib/src/loaders/require.dart | 11 ------- dwds/test/evaluate_common.dart | 31 ++++++++++++------- dwds/test/fixtures/context.dart | 19 +++++------- dwds/test/fixtures/server.dart | 2 ++ dwds/test/instances/instance_test.dart | 2 +- .../lib/src/asset_server.dart | 16 ++-------- frontend_server_common/lib/src/devfs.dart | 26 +++++++++------- 10 files changed, 55 insertions(+), 65 deletions(-) diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 5356510ef..1030e320d 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -1,4 +1,6 @@ -## 19.0.2-wip +## 20.0.0-wip + +- Allow clients to specify the `basePath` for connected app. - [#2160](https://github.com/dart-lang/webdev/pull/2160) ## 19.0.1 diff --git a/dwds/lib/dart_web_debug_service.dart b/dwds/lib/dart_web_debug_service.dart index 7d8bd7ea0..06b774ca5 100644 --- a/dwds/lib/dart_web_debug_service.dart +++ b/dwds/lib/dart_web_debug_service.dart @@ -85,6 +85,7 @@ class Dwds { bool emitDebugEvents = true, bool isInternalBuild = false, Future Function()? isFlutterApp, + String basePath = '', }) async { globalLoadStrategy = loadStrategy; isFlutterApp ??= () => Future.value(true); @@ -150,6 +151,7 @@ class Dwds { injected, spawnDds, launchDevToolsInNewWindow, + basePath, ); return Dwds._( diff --git a/dwds/lib/src/handlers/dev_handler.dart b/dwds/lib/src/handlers/dev_handler.dart index d98d73deb..384f19546 100644 --- a/dwds/lib/src/handlers/dev_handler.dart +++ b/dwds/lib/src/handlers/dev_handler.dart @@ -23,7 +23,6 @@ import 'package:dwds/src/dwds_vm_client.dart'; import 'package:dwds/src/events.dart'; import 'package:dwds/src/handlers/injector.dart'; import 'package:dwds/src/handlers/socket_connections.dart'; -import 'package:dwds/src/loaders/require.dart'; import 'package:dwds/src/readers/asset_reader.dart'; import 'package:dwds/src/servers/devtools.dart'; import 'package:dwds/src/servers/extension_backend.dart'; @@ -69,6 +68,7 @@ class DevHandler { final bool _launchDevToolsInNewWindow; final ExpressionCompiler? _expressionCompiler; final DwdsInjector _injected; + final String _basePath; /// Null until [close] is called. /// @@ -91,6 +91,7 @@ class DevHandler { this._injected, this._spawnDds, this._launchDevToolsInNewWindow, + this._basePath, ) { _subs.add(buildResults.listen(_emitBuildResults)); _listen(); @@ -196,7 +197,7 @@ class DevHandler { 'localhost', webkitDebugger, executionContext, - basePathForServerUri(appTab.url), + _basePath, _assetReader, appConnection, _urlEncoder, @@ -587,7 +588,7 @@ class DevHandler { _hostname, extensionDebugger, executionContext, - basePathForServerUri(tabUrl), + _basePath, _assetReader, connection, _urlEncoder, diff --git a/dwds/lib/src/loaders/require.dart b/dwds/lib/src/loaders/require.dart index a8b0f1e68..5d9d8f78b 100644 --- a/dwds/lib/src/loaders/require.dart +++ b/dwds/lib/src/loaders/require.dart @@ -11,17 +11,6 @@ import 'package:dwds/src/services/expression_compiler.dart'; import 'package:path/path.dart' as p; import 'package:shelf/shelf.dart'; -/// Find the path we are serving from the url. -/// -/// Example: -/// https://localhost/base/index.html => base -/// https://localhost/base => base -String basePathForServerUri(String url) { - final uri = Uri.parse(url); - var base = uri.path.endsWith('.html') ? p.dirname(uri.path) : uri.path; - return base = base.startsWith('/') ? base.substring(1) : base; -} - String removeJsExtension(String path) => path.endsWith('.js') ? p.withoutExtension(path) : path; diff --git a/dwds/test/evaluate_common.dart b/dwds/test/evaluate_common.dart index a4dfaa8fd..0354eef59 100644 --- a/dwds/test/evaluate_common.dart +++ b/dwds/test/evaluate_common.dart @@ -155,11 +155,15 @@ void testAll({ scope: scope, ); - getInstanceRef(frame, expr, {scope}) async => await evaluateInFrame( - frame, - expr, - scope: scope, - ) as InstanceRef; + getInstanceRef(frame, expr, {scope}) async { + final result = await evaluateInFrame( + frame, + expr, + scope: scope, + ); + expect(result, isA()); + return result as InstanceRef; + } getInstance(InstanceRef ref) async => await context.service.getObject(isolateId, ref.id!) as Instance; @@ -494,7 +498,7 @@ void testAll({ expect(result, matchInstanceRef('23')); }); - }, solo: true); + }); test('evaluate expression in a class constructor in a library', () async { @@ -675,12 +679,15 @@ void testAll({ libraryId, expr, { scope, - }) async => - await evaluate( - libraryId, - expr, - scope: scope, - ) as InstanceRef; + }) async { + final result = await evaluate( + libraryId, + expr, + scope: scope, + ); + expect(result, isA()); + return result as InstanceRef; + } String getRootLibraryId() { expect(isolate.rootLib, isNotNull); diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index 1ad175f01..9811fda2e 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -211,7 +211,7 @@ class TestContext { Stream buildResults; RequireStrategy requireStrategy; String basePath = ''; - String index = project.filePathToServe; + String filePathToServe = project.filePathToServe; _port = await findUnusedPort(); switch (compilationMode) { @@ -280,17 +280,12 @@ class TestContext { break; case CompilationMode.frontendServer: { - index = webCompatiblePath([ + filePathToServe = webCompatiblePath([ project.directoryToServe, project.filePathToServe, ]); - print('Directory: ${project.directoryToServe}'); - print('Index: ${project.filePathToServe}'); - - //index = project.filePathToServe; - - print('Context Index: $index'); + _logger.info('Path to serve: $filePathToServe'); final entry = p.toUri( p.join(project.webAssetsPath, project.dartEntryFileName), @@ -322,8 +317,7 @@ class TestContext { fileSystem, hostname, assetServerPort, - index, - //p.join(project.directoryToServe, project.filePathToServe), + filePathToServe, ); if (enableExpressionEvaluation) { @@ -402,11 +396,12 @@ class TestContext { isFlutterApp, isInternalBuild, sdkLayout, + basePath, ); _appUrl = basePath.isEmpty - ? 'http://localhost:$port/$index' - : 'http://localhost:$port/$basePath/$index'; + ? 'http://localhost:$port/$filePathToServe' + : 'http://localhost:$port/$basePath/$filePathToServe'; if (launchChrome) { await _webDriver?.get(appUrl); diff --git a/dwds/test/fixtures/server.dart b/dwds/test/fixtures/server.dart index 6396e8566..63c1c83b6 100644 --- a/dwds/test/fixtures/server.dart +++ b/dwds/test/fixtures/server.dart @@ -82,6 +82,7 @@ class TestServer { bool isFlutterApp, bool isInternalBuild, TestSdkLayout sdkLayout, + String basePath, ) async { var pipeline = const Pipeline(); @@ -132,6 +133,7 @@ class TestServer { return DevTools(server.address.host, server.port, server); } : null, + basePath: basePath, ); final server = await startHttpServer('localhost', port: port); diff --git a/dwds/test/instances/instance_test.dart b/dwds/test/instances/instance_test.dart index a74cc9667..dec094009 100644 --- a/dwds/test/instances/instance_test.dart +++ b/dwds/test/instances/instance_test.dart @@ -99,7 +99,7 @@ void _runTests({ expect(classRef.name, 'Null'); expect(classRef.id, 'classes|dart:core|Null'); expect(inspector.isDisplayableObject(ref), isTrue); - }, solo: true); + }); test('for a double', () async { final remoteObject = await libraryPublicFinal(compilationMode); diff --git a/frontend_server_common/lib/src/asset_server.dart b/frontend_server_common/lib/src/asset_server.dart index ad8074d19..2a837dc38 100644 --- a/frontend_server_common/lib/src/asset_server.dart +++ b/frontend_server_common/lib/src/asset_server.dart @@ -13,7 +13,6 @@ import 'package:dwds/asset_reader.dart'; import 'package:file/file.dart'; import 'package:logging/logging.dart'; import 'package:mime/mime.dart' as mime; -import 'package:path/path.dart' as p; import 'package:shelf/shelf.dart' as shelf; import 'package:test_common/test_sdk_layout.dart'; @@ -44,11 +43,7 @@ class TestAssetServer implements AssetReader { this._fileSystem, this._sdkLayout, ) { - // Base from index file replaces the base path in main.dart.js - // and everything that is loaded from there. - final baseFromIndex = _parseBasePathFromIndexHtml(index); - basePath = baseFromIndex.isNotEmpty ? baseFromIndex : p.dirname(index); - print('BASE PATH: $basePath'); + basePath = _parseBasePathFromIndexHtml(index); } bool hasFile(String path) => _files.containsKey(path); @@ -87,12 +82,10 @@ class TestAssetServer implements AssetReader { // Assets are served via GET only. return shelf.Response.notFound(''); } - print('Request: ${request.url.path}'); final requestPath = _stripBasePath(request.url.path, basePath); if (requestPath == null) { return shelf.Response.notFound(''); } - print('Stripped request: $requestPath'); var headers = {}; @@ -252,12 +245,7 @@ class TestAssetServer implements AssetReader { return dartFile; } - var segments = path.split('/'); - if (segments.contains('packages')) { - segments = segments.skipWhile((value) => value != 'packages').toList(); - path = segments.join('/'); - } - print('Segments: $segments'); + final segments = path.split('/'); // The file might have been a package file which is signaled by a // `/packages//` request. diff --git a/frontend_server_common/lib/src/devfs.dart b/frontend_server_common/lib/src/devfs.dart index 100e23e29..58c86d306 100644 --- a/frontend_server_common/lib/src/devfs.dart +++ b/frontend_server_common/lib/src/devfs.dart @@ -62,17 +62,21 @@ class WebDevFS { final mainPath = mainUri.toFilePath(); final outputDirectoryPath = fileSystem.file(mainPath).parent.path; final entryPoint = mainUri.toString(); - print('Entrypoint: $entryPoint'); - final directory = p.dirname(entryPoint); - final require = p.join(directory, 'require.js'); - final stackMapper = p.join(directory, 'stack_trace_mapper.js'); - final main = p.join(directory, 'main.dart.js'); - final bootstrap = p.join(directory, 'main_module.bootstrap.js'); - - // final require = 'require.js'; - // final stackMapper = 'stack_trace_mapper.js'; - // final main = 'main.dart.js'; - // final bootstrap = 'main_module.bootstrap.js'; + + var require = 'require.js'; + var stackMapper = 'stack_trace_mapper.js'; + var main = 'main.dart.js'; + var bootstrap = 'main_module.bootstrap.js'; + + // If base path is not overwritten, use main's subdirectory + // to store all files, so the paths match the requests. + if (assetServer.basePath.isEmpty) { + final directory = p.dirname(entryPoint); + require = p.join(directory, 'require.js'); + stackMapper = p.join(directory, 'stack_trace_mapper.js'); + main = p.join(directory, 'main.dart.js'); + bootstrap = p.join(directory, 'main_module.bootstrap.js'); + } assetServer.writeFile( entryPoint, fileSystem.file(mainPath).readAsStringSync()); From 30cf46cd20a28d70063ebf0a121858f51138cf00 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 28 Jun 2023 13:21:08 -0700 Subject: [PATCH 5/8] update pubspec and build --- dwds/lib/src/version.dart | 2 +- dwds/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dwds/lib/src/version.dart b/dwds/lib/src/version.dart index d21d38d58..8892ec587 100644 --- a/dwds/lib/src/version.dart +++ b/dwds/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '19.0.2-wip'; +const packageVersion = '20.0.0-wip'; diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml index 55c155181..2f62a60ec 100644 --- a/dwds/pubspec.yaml +++ b/dwds/pubspec.yaml @@ -1,6 +1,6 @@ name: dwds # Every time this changes you need to run `dart run build_runner build`. -version: 19.0.2-wip +version: 20.0.0-wip description: >- A service that proxies between the Chrome debug protocol and the Dart VM service protocol. From 3cd0b8fa2359e045669e5b29fac3b9fa24932cbc Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 28 Jun 2023 14:57:01 -0700 Subject: [PATCH 6/8] Require AssetReader to provide a base path --- dwds/CHANGELOG.md | 2 +- dwds/lib/dart_web_debug_service.dart | 2 -- dwds/lib/src/handlers/dev_handler.dart | 4 ---- .../src/loaders/frontend_server_require.dart | 3 +-- dwds/lib/src/readers/asset_reader.dart | 12 ++++++++++++ .../readers/frontend_server_asset_reader.dart | 17 ++++++++++++----- .../src/readers/proxy_server_asset_reader.dart | 3 +++ dwds/lib/src/services/debug_service.dart | 2 +- dwds/test/fixtures/context.dart | 4 +--- dwds/test/fixtures/fakes.dart | 3 +++ dwds/test/fixtures/server.dart | 2 -- .../frontend_server_asset_reader_test.dart | 4 ++-- .../lib/src/asset_server.dart | 7 +++++-- 13 files changed, 41 insertions(+), 24 deletions(-) diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 1030e320d..14df629c8 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -1,6 +1,6 @@ ## 20.0.0-wip -- Allow clients to specify the `basePath` for connected app. - [#2160](https://github.com/dart-lang/webdev/pull/2160) +- Allow clients to specify the `basePath` on `AssetReader`. - [#2160](https://github.com/dart-lang/webdev/pull/2160) ## 19.0.1 diff --git a/dwds/lib/dart_web_debug_service.dart b/dwds/lib/dart_web_debug_service.dart index 06b774ca5..7d8bd7ea0 100644 --- a/dwds/lib/dart_web_debug_service.dart +++ b/dwds/lib/dart_web_debug_service.dart @@ -85,7 +85,6 @@ class Dwds { bool emitDebugEvents = true, bool isInternalBuild = false, Future Function()? isFlutterApp, - String basePath = '', }) async { globalLoadStrategy = loadStrategy; isFlutterApp ??= () => Future.value(true); @@ -151,7 +150,6 @@ class Dwds { injected, spawnDds, launchDevToolsInNewWindow, - basePath, ); return Dwds._( diff --git a/dwds/lib/src/handlers/dev_handler.dart b/dwds/lib/src/handlers/dev_handler.dart index 384f19546..8cc86e3c7 100644 --- a/dwds/lib/src/handlers/dev_handler.dart +++ b/dwds/lib/src/handlers/dev_handler.dart @@ -68,7 +68,6 @@ class DevHandler { final bool _launchDevToolsInNewWindow; final ExpressionCompiler? _expressionCompiler; final DwdsInjector _injected; - final String _basePath; /// Null until [close] is called. /// @@ -91,7 +90,6 @@ class DevHandler { this._injected, this._spawnDds, this._launchDevToolsInNewWindow, - this._basePath, ) { _subs.add(buildResults.listen(_emitBuildResults)); _listen(); @@ -197,7 +195,6 @@ class DevHandler { 'localhost', webkitDebugger, executionContext, - _basePath, _assetReader, appConnection, _urlEncoder, @@ -588,7 +585,6 @@ class DevHandler { _hostname, extensionDebugger, executionContext, - _basePath, _assetReader, connection, _urlEncoder, diff --git a/dwds/lib/src/loaders/frontend_server_require.dart b/dwds/lib/src/loaders/frontend_server_require.dart index 485528809..8de6262b5 100644 --- a/dwds/lib/src/loaders/frontend_server_require.dart +++ b/dwds/lib/src/loaders/frontend_server_require.dart @@ -36,9 +36,8 @@ class FrontendServerRequireStrategyProvider { this._assetReader, this._packageUriMapper, this._digestsProvider, - this._basePath, this._appEntrypoint, - ); + ) : _basePath = _assetReader.basePath; RequireStrategy get strategy => _requireStrategy; diff --git a/dwds/lib/src/readers/asset_reader.dart b/dwds/lib/src/readers/asset_reader.dart index 98fac9a50..896eb527e 100644 --- a/dwds/lib/src/readers/asset_reader.dart +++ b/dwds/lib/src/readers/asset_reader.dart @@ -11,6 +11,18 @@ typedef UrlEncoder = Future Function(String url); /// A reader for Dart sources and related source maps. abstract class AssetReader { + /// Base path of the application, for example, set up in the index file: + /// + /// ``` + /// + /// + /// + /// + /// + /// + /// ``` + String get basePath; + /// Returns the contents for a source map at the provided server path, or /// null if the resource does not exist. Future sourceMapContents(String serverPath); diff --git a/dwds/lib/src/readers/frontend_server_asset_reader.dart b/dwds/lib/src/readers/frontend_server_asset_reader.dart index d9cb90912..d2f8c32d7 100644 --- a/dwds/lib/src/readers/frontend_server_asset_reader.dart +++ b/dwds/lib/src/readers/frontend_server_asset_reader.dart @@ -20,6 +20,7 @@ class FrontendServerAssetReader implements AssetReader { final File _jsonIncremental; final String _packageRoot; final Future _packageConfig; + final String _basePath; /// Map of Dart module server path to source map contents. final _mapContents = {}; @@ -37,19 +38,25 @@ class FrontendServerAssetReader implements AssetReader { /// /// [_packageRoot] is the path to the directory that contains a /// `.dart_tool/package_config.json` file for the application. - FrontendServerAssetReader( - String outputPath, - this._packageRoot, - ) : _mapOriginal = File('$outputPath.map'), + FrontendServerAssetReader({ + required String outputPath, + required String packageRoot, + String? basePath, + }) : _packageRoot = packageRoot, + _basePath = basePath ?? '', + _mapOriginal = File('$outputPath.map'), _mapIncremental = File('$outputPath.incremental.map'), _jsonOriginal = File('$outputPath.json'), _jsonIncremental = File('$outputPath.incremental.json'), _packageConfig = loadPackageConfig( File( - p.absolute(p.join(_packageRoot, '.dart_tool/package_config.json')), + p.absolute(p.join(packageRoot, '.dart_tool/package_config.json')), ), ); + @override + String get basePath => _basePath; + @override Future dartSourceContents(String serverPath) async { if (serverPath.endsWith('.dart')) { diff --git a/dwds/lib/src/readers/proxy_server_asset_reader.dart b/dwds/lib/src/readers/proxy_server_asset_reader.dart index 48ba343ce..c36c800e3 100644 --- a/dwds/lib/src/readers/proxy_server_asset_reader.dart +++ b/dwds/lib/src/readers/proxy_server_asset_reader.dart @@ -38,6 +38,9 @@ class ProxyServerAssetReader implements AssetReader { _handler = proxyHandler(url, client: _client); } + @override + String get basePath => ''; + @override Future dartSourceContents(String serverPath) => _readResource(serverPath); diff --git a/dwds/lib/src/services/debug_service.dart b/dwds/lib/src/services/debug_service.dart index 96393a967..a0f8fae99 100644 --- a/dwds/lib/src/services/debug_service.dart +++ b/dwds/lib/src/services/debug_service.dart @@ -220,7 +220,6 @@ class DebugService { String hostname, RemoteDebugger remoteDebugger, ExecutionContext executionContext, - String root, AssetReader assetReader, AppConnection appConnection, UrlEncoder? urlEncoder, { @@ -230,6 +229,7 @@ class DebugService { bool useSse = false, ExpressionCompiler? expressionCompiler, }) async { + final root = assetReader.basePath; final chromeProxyService = await ChromeProxyService.create( remoteDebugger, root, diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index 9811fda2e..c6285bfb6 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -285,7 +285,7 @@ class TestContext { project.filePathToServe, ]); - _logger.info('Path to serve: $filePathToServe'); + _logger.info('Serving: $filePathToServe'); final entry = p.toUri( p.join(project.webAssetsPath, project.dartEntryFileName), @@ -332,7 +332,6 @@ class TestContext { assetReader, packageUriMapper, () async => {}, - basePath, project.dartEntryFilePackageUri, ).strategy; @@ -396,7 +395,6 @@ class TestContext { isFlutterApp, isInternalBuild, sdkLayout, - basePath, ); _appUrl = basePath.isEmpty diff --git a/dwds/test/fixtures/fakes.dart b/dwds/test/fixtures/fakes.dart index fe1f93330..5274a06af 100644 --- a/dwds/test/fixtures/fakes.dart +++ b/dwds/test/fixtures/fakes.dart @@ -393,6 +393,9 @@ class FakeAssetReader implements AssetReader { _dartSource = dartSource, _sourceMap = sourceMap; + @override + String get basePath => ''; + @override Future dartSourceContents(String serverPath) { return _throwUnimplementedOrReturnContents(_dartSource); diff --git a/dwds/test/fixtures/server.dart b/dwds/test/fixtures/server.dart index 63c1c83b6..6396e8566 100644 --- a/dwds/test/fixtures/server.dart +++ b/dwds/test/fixtures/server.dart @@ -82,7 +82,6 @@ class TestServer { bool isFlutterApp, bool isInternalBuild, TestSdkLayout sdkLayout, - String basePath, ) async { var pipeline = const Pipeline(); @@ -133,7 +132,6 @@ class TestServer { return DevTools(server.address.host, server.port, server); } : null, - basePath: basePath, ); final server = await startHttpServer('localhost', port: port); diff --git a/dwds/test/readers/frontend_server_asset_reader_test.dart b/dwds/test/readers/frontend_server_asset_reader_test.dart index de45b8310..e11c29dcd 100644 --- a/dwds/test/readers/frontend_server_asset_reader_test.dart +++ b/dwds/test/readers/frontend_server_asset_reader_test.dart @@ -45,8 +45,8 @@ void main() { setUp(() async { await createTempFixtures(); assetReader = FrontendServerAssetReader( - p.join(tempFixtures.path, 'main.dart.dill'), - packagesDir, + outputPath: p.join(tempFixtures.path, 'main.dart.dill'), + packageRoot: packagesDir, ); assetReader.updateCaches(); }); diff --git a/frontend_server_common/lib/src/asset_server.dart b/frontend_server_common/lib/src/asset_server.dart index 2a837dc38..784e634f9 100644 --- a/frontend_server_common/lib/src/asset_server.dart +++ b/frontend_server_common/lib/src/asset_server.dart @@ -17,7 +17,7 @@ import 'package:shelf/shelf.dart' as shelf; import 'package:test_common/test_sdk_layout.dart'; class TestAssetServer implements AssetReader { - late final String basePath; + late final String _basePath; final String index; final _logger = Logger('TestAssetServer'); @@ -43,9 +43,12 @@ class TestAssetServer implements AssetReader { this._fileSystem, this._sdkLayout, ) { - basePath = _parseBasePathFromIndexHtml(index); + _basePath = _parseBasePathFromIndexHtml(index); } + @override + String get basePath => _basePath; + bool hasFile(String path) => _files.containsKey(path); Uint8List getFile(String path) => _files[path]!; From 024a64d2e7046ff88592dc0e861598634d7be1d2 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 5 Jul 2023 14:04:43 -0700 Subject: [PATCH 7/8] Fix test failures on windows --- frontend_server_common/lib/src/devfs.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend_server_common/lib/src/devfs.dart b/frontend_server_common/lib/src/devfs.dart index 58c86d306..c0c7f371d 100644 --- a/frontend_server_common/lib/src/devfs.dart +++ b/frontend_server_common/lib/src/devfs.dart @@ -72,10 +72,10 @@ class WebDevFS { // to store all files, so the paths match the requests. if (assetServer.basePath.isEmpty) { final directory = p.dirname(entryPoint); - require = p.join(directory, 'require.js'); - stackMapper = p.join(directory, 'stack_trace_mapper.js'); - main = p.join(directory, 'main.dart.js'); - bootstrap = p.join(directory, 'main_module.bootstrap.js'); + require = '$directory/require.js'; + stackMapper = '$directory/stack_trace_mapper.js'; + main = '$directory/main.dart.js'; + bootstrap = '$directory/main_module.bootstrap.js'; } assetServer.writeFile( From 04463228109627a41b9fc0475c0cad71b253a0e3 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 5 Jul 2023 14:17:10 -0700 Subject: [PATCH 8/8] Merge with master --- dwds/lib/src/version.dart | 4 ---- dwds/pubspec.yaml | 4 ---- 2 files changed, 8 deletions(-) diff --git a/dwds/lib/src/version.dart b/dwds/lib/src/version.dart index 7cc5992a7..8892ec587 100644 --- a/dwds/lib/src/version.dart +++ b/dwds/lib/src/version.dart @@ -1,6 +1,2 @@ // Generated code. Do not modify. -<<<<<<< HEAD const packageVersion = '20.0.0-wip'; -======= -const packageVersion = '19.0.3-wip'; ->>>>>>> b672e98a4f1071bace009da84b6544151977a2b6 diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml index fb66ede49..2f62a60ec 100644 --- a/dwds/pubspec.yaml +++ b/dwds/pubspec.yaml @@ -1,10 +1,6 @@ name: dwds # Every time this changes you need to run `dart run build_runner build`. -<<<<<<< HEAD version: 20.0.0-wip -======= -version: 19.0.3-wip ->>>>>>> b672e98a4f1071bace009da84b6544151977a2b6 description: >- A service that proxies between the Chrome debug protocol and the Dart VM service protocol.