package:web

repository·main·Indexed 41 days ago

https://github.com/dart-lang/web

A lightweight, zero-overhead replacement for dart:html providing browser API bindings for Dart code compiled to JavaScript or WebAssembly. The project includes a toolset for generating Dart interfaces from TypeScript declaration files (.d.ts) via js_interop_gen and from Web IDL definitions via web_generator.

Tokens
7.2K
Snippets
23
Records
29
Agent score
52%

What's inside package:web

  1. Use js_interop utility functions and types

    main
    The js_interop package provides utility functions and types designed to work with dart:js_interop and dart:js_interop_unsafe. Use this package to simplify JavaScript interop operations in Dart, providing helper tools for handling JS values and types more effectively.
  2. How the Web IDL generator handles interfaces and types

    main

    The generator follows specific conventions to map Web IDL to Dart:

    Interfaces

    • Emitted as extension types wrapping and implementing JSObject.
    • Inheritance is maintained via implements between extension types.
    • Members from partial interfaces or mixins are merged directly into the primary interfaces.

    Types

    • Generics: JSArray and JSPromise include their generic type.
    • Enums: Typedef'd to String.
    • Callbacks: Typedef'd to JSFunction.
    • Primitives: Prefers Dart primitives (e.g., String) over JS equivalents (e.g., JSString) whenever possible. However, if a type is in a generic position, it is replaced with the JS equivalent to respect the JSAny? type bound.
    • Union Types: Computed by finding the least upper bound in the JS type hierarchy (where every interface is a JSObject).
    • Dictionaries/Typedefs: Only emitted if they are utilized by another API.
  3. How package:web is generated

    main
    The bindings in this package are automatically generated from Web IDL definitions using the web_generator tool. For details on the generation conventions and how to run the tools to update bindings or dependencies, refer to the web_generator documentation.
  4. How TypeScript types are mapped to Dart

    main

    The generator follows specific conventions to map TypeScript definitions to Dart js_interop code:

    Core Mapping Logic

    • Top Level Declarations: Handled as top-level Dart external declarations annotated with @JS.
    • Enums: Represented as extension types with static members. If values are unknown, the representation type is an interop type.
    • Interfaces and Classes: Emitted as extension types wrapping JSObject. Inheritance is maintained via implements. Readonly properties become getters. Overriding signatures use @redeclare.
    • Namespaces: Converted to extension types on JSObject with static members. Nested namespaces are generated as static getters.
    • Types:
      • Basic JS types map to dart:js_interop types.
      • never types (from const or readonly) are annotated with @doNotStore.
      • Web types automatically map to package:web types.
      • Anonymous Unions/Intersections: Represented as extension types with cast members. An intersection with null or undefined results in never.
      • Anonymous Objects: Represented as extension types with an object literal constructor.
      • Anonymous Closures/Construct Signatures: Represented as extension types on JSFunction overriding the call method.
      • Generics: Represented as normal Dart generics, constrained by JSAny by default.
      • typeof: References the type of the declaration (e.g., JSFunction for functions).
      • keyof: Represented as unions of the keys for the operand type.

    Other Features

    • Imports/Exports: If imported files are in the input, they are treated as Dart imports; otherwise, they are generated in-place.
    • Documentation: JSDoc is supported and mapped to Dart annotations like @deprecated and @experimental.
  5. Update to the latest Web IDL versions and regenerate

    main

    You can update the package to use newer IDL versions using one of two methods:

    1. Automatic update: Run the script with the --update flag.
    2. Manual update: Edit lib/src/package.json to specify desired IDL versions, then run update_idl_bindings.dart to regenerate the code.

    To include the latest documentation from MDN in your generated code, you must first scrape the MDN data and then regenerate the bindings.

    # Update IDL versions and regenerate automatically
    dart bin/update_idl_bindings.dart --update
    
    # Update MDN documentation data
    dart bin/scrape_mdn.dart
    
    # Regenerate bindings after updating MDN data
    dart bin/update_idl_bindings.dart
  6. Use package:web for browser API bindings

    main

    Use package:web to access browser APIs from Dart code compiled to either JavaScript or WebAssembly. It provides lightweight, zero-overhead bindings built around Dart's JS interop, intended as the replacement for dart:html and other legacy web libraries.

    To use it, import package:web/web.dart and interact with browser objects like document directly.

    import 'package:web/web.dart';
    
    void main() {
      final div = document.querySelector('div')!;
      div.text = 'Text set at ${DateTime.now()}';
    }
  7. Generate Dart interfaces from Web IDL files

    main

    To generate Dart interfaces for a specific .idl file, run the update_idl_bindings.dart script from the root of the package. If you provide multiple files, the final argument is treated as the output directory.

    dart bin/update_idl_bindings.dart <path_to_idl_file> [output_directory]
  8. Migrate from dart:html to package:web

    main

    package:web is the long-term web interop solution for Dart, replacing dart:html.

    Key behavioral change for document.cookie: In package:web, document.cookie is non-nullable and always returns a String. This follows the Web IDL specification. Unlike dart:html, which allowed a nullable return for legacy browser compatibility, package:web will return an empty string ("") if no cookies are present instead of null.

  9. Configure the js_interop_gen via YAML

    main

    You can configure the generator's behavior (such as variadic argument counts, preambles, or TypeScript compiler options) using a YAML configuration file. This is passed via the --config flag.

    Using a configuration file is equivalent to passing multiple CLI flags. For example, the following YAML configuration:

    input: a.d.ts
    output: b.d.ts
    ts-config-file: tsconfig.json

    is equivalent to:

    dart run js_interop_gen -o b.d.ts --ts-config tsconfig.json a.d.ts
  10. Run dart fix tests manually

    main

    To manually verify the dart fix refactorings provided by this package, navigate to the test_fixes directory and run the dart fix command with the --compare-to-golden flag. This compares the results of the refactoring against established golden files.

    cd test_fixes
    dart fix --compare-to-golden
  11. Generate Dart interfaces from TS Declarations

    main

    Use the js_interop_gen.dart entrypoint to generate Dart interfaces from TypeScript .d.ts files. The generator is written in Dart, compiled to JavaScript, and requires a Node.js runtime.

    Requirements

    • Node.js v22 or newer is required. Older versions are not supported and may cause runtime failures.
    # Basic generation
    dart run js_interop_gen <input.d.ts>
    
    # Generation with specific output file
    dart run js_interop_gen -o <output> <input.d.ts>
    
    # Generation with multiple files (output is treated as a directory)
    dart run js_interop_gen <file1.d.ts> <file2.d.ts> -o <output_dir>