Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate usage of dart:html to package:web to support WASM #801

Closed
IchordeDionysos opened this issue Feb 17, 2024 · 1 comment · Fixed by #802
Closed

Migrate usage of dart:html to package:web to support WASM #801

IchordeDionysos opened this issue Feb 17, 2024 · 1 comment · Fixed by #802
Labels
type-enhancement A request for a change that isn't a bug

Comments

@IchordeDionysos
Copy link
Contributor

To support using this fundamental library in WASM it can't use dart:html which only works when compiled to JavaScript not WASM.

Enable working in a WASM environment usages of dart:html need to be migrated to package:web.

Usages of dart:html:
https://github.com/search?q=repo%3Adart-lang%2Fi18n+%22dart%3Ahtml%22+path%3A%2F%5Epkgs%5C%2Fintl%5C%2Flib%5C%2F%2F&type=code

Migration guide:
https://dart.dev/interop/js-interop/package-web

@IchordeDionysos IchordeDionysos added the type-enhancement A request for a change that isn't a bug label Feb 17, 2024
@IchordeDionysos
Copy link
Contributor Author

There is one issue with moving from dart:html to package:web (or another WASM ready option).

We need to remove dart:html from https://github.com/dart-lang/i18n/blob/main/pkgs/intl/lib/src/http_request_data_reader.dart#L11.

There are a couple of options:

  1. Use package:web and use the deprecated HttpRequest class of package:web:
  • Positive: It supports WASM
  • Positive: It uses XMLHttpRequest for maximum compatibility
  • Downside: It's a deprecated method
  • Downside: It doesn't support timeouts
Option 1.1 (no timeout)

class HttpRequestDataReader implements LocaleDataReader {
  /// The base url from which we read the data.
  String url;

  HttpRequestDataReader(this.url);

  @override
  Future<String> read(String locale) {
    return HttpRequest.getString('$url$locale.json');
  }
}

Option 1.2 (artificial timeout):

class HttpRequestDataReader implements LocaleDataReader {
  /// The base url from which we read the data.
  String url;

  HttpRequestDataReader(this.url);

  @override
  Future<String> read(String locale) {
    return Future.any([
      Future.delayed(Duration(seconds: 5)).then((_) {
        throw TimeoutException('Timeout while reading $locale');
      }),
      HttpRequest.getString('$url$locale.json')
    ]);
  }
}

  1. Use package:web and use the Fetch API:
  • Positive: It supports WASM
  • Positive: It allows timeouts using the AbortSignal
  • Positive: It uses modern web APIs
  • Downside: It does not support Browsers released in 2015/1016
Option 2:

class HttpRequestDataReader implements LocaleDataReader {
  /// The base url from which we read the data.
  String url;

  HttpRequestDataReader(this.url);

  @override
  Future<String> read(String locale) {
    final controller = AbortController();

    Future.delayed(Duration(seconds: 5)).then((_) {
      controller.abort();
    });

    return window
        .fetch(
          '$url$locale.json'.toJS,
          RequestInit(
            method: 'GET',
            signal: controller.signal,
          ),
        )
        .toDart
        .then((response) {
      // Note: file:// URIs have status of 0.
      if ((response.status >= 200 && response.status < 300) ||
          response.status == 0 ||
          response.status == 304) {
        return response.text().toDart.then((text) => text.toDart);
      } else {
        throw Exception('Failed to load locale data for $locale');
      }
    });
  }
}

  1. Use package:http:
Option 3

class HttpRequestDataReader implements LocaleDataReader {
  /// The base url from which we read the data.
  String url;

  HttpRequestDataReader(this.url);

  @override
  Future<String> read(String locale) {
    final Client client = Client();
    return client.get(Uri.parse('$url$locale.json')).then((response) {
      if ((response.statusCode >= 200 && response.statusCode < 300) ||
          response.statusCode == 0 ||
          response.statusCode == 304) {
        return response.body;
      } else {
        throw Exception('Failed to load $locale');
      }
    });
  }
}

  1. Use package:http use Future.delayed and ignore the request if it takes too long (accept that the request might not be timed out):
  • Positive: it supports WASM
  • Positive: It uses XMLHttpRequest for maximum compatibility
  • Positive: We can close the connection after 5 seconds
Option 4

// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// This contains a reader that accesses data using the HttpRequest
/// facility, and thus works only in the web browser.

library http_request_data_reader;

import 'dart:async';
import 'dart:js_interop';
// todo: Rework this to use the http package once https://github.com/dart-lang/http/issues/424 is resolved.
import 'package:http/http.dart';
import 'intl_helpers.dart';

class HttpRequestDataReader implements LocaleDataReader {
  /// The base url from which we read the data.
  String url;

  HttpRequestDataReader(this.url);

  @override
  Future<String> read(String locale) {
    final Client client = Client();
    return Future.any([
      Future.delayed(Duration(seconds: 5)).then((_) {
        client.close();
        throw TimeoutException('Timeout while reading $locale');
      }),
      client.get(Uri.parse('$url$locale.json')).then((response) {
        if ((response.statusCode >= 200 && response.statusCode < 300) ||
            response.statusCode == 0 ||
            response.statusCode == 304) {
          return response.body;
        } else {
          throw Exception('Failed to load $locale');
        }
      }),
    ]);
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant