Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 37 additions & 27 deletions web_generator/bin/update_idl_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,17 @@ $_usage''');

// Run app with `node`.
final generateAll = argResult['generate-all'] as bool;
final inputFiles = argResult['input'] as List<String>;
await runProc(
'node',
[
'main.mjs',
'--idl',
'--output=${p.join(_webPackagePath, 'lib', 'src')}',
for (String inputFile in inputFiles) '--input=$inputFile',
if (inputFiles.isEmpty)
'--output=${p.join(_webPackagePath, 'lib', 'src')}'
else
'--output=${argResult['output'] as String? ?? p.current}',
if (generateAll) '--generate-all',
],
workingDirectory: bindingsGeneratorPath,
Expand All @@ -89,16 +94,17 @@ $_usage''');
// delete context file
await contextFile.delete();

// Update readme.
final readmeFile =
File(p.normalize(p.fromUri(Platform.script.resolve('../README.md'))));
if (inputFiles.isEmpty) {
// Update readme.
final readmeFile =
File(p.normalize(p.fromUri(Platform.script.resolve('../README.md'))));

final sourceContent = readmeFile.readAsStringSync();
final sourceContent = readmeFile.readAsStringSync();

final cssVersion = _packageLockVersion(_webRefCss);
final elementsVersion = _packageLockVersion(_webRefElements);
final idlVersion = _packageLockVersion(_webRefIdl);
final versions = '''
final cssVersion = _packageLockVersion(_webRefCss);
final elementsVersion = _packageLockVersion(_webRefElements);
final idlVersion = _packageLockVersion(_webRefIdl);
final versions = '''
$_startComment
| Item | Version |
| --- | --: |
Expand All @@ -107,15 +113,16 @@ $_startComment
| `$_webRefIdl` | [$idlVersion](https://www.npmjs.com/package/$_webRefIdl/v/$idlVersion) |
''';

final newContent =
sourceContent.substring(0, sourceContent.indexOf(_startComment)) +
versions +
sourceContent.substring(sourceContent.indexOf(_endComment));
if (newContent == sourceContent) {
print(ansi.styleBold.wrap('No update for readme.'));
} else {
print(ansi.styleBold.wrap('Updating readme for IDL version $idlVersion'));
readmeFile.writeAsStringSync(newContent, mode: FileMode.writeOnly);
final newContent =
sourceContent.substring(0, sourceContent.indexOf(_startComment)) +
versions +
sourceContent.substring(sourceContent.indexOf(_endComment));
if (newContent == sourceContent) {
print(ansi.styleBold.wrap('No update for readme.'));
} else {
print(ansi.styleBold.wrap('Updating readme for IDL version $idlVersion'));
readmeFile.writeAsStringSync(newContent, mode: FileMode.writeOnly);
}
}
}

Expand Down Expand Up @@ -161,23 +168,26 @@ final _endComment =
'<!-- END updated by $_scriptPOSIXPath. Do not modify by hand -->';

final _usage = '''
Global Options:
${_parser.usage}

${ansi.styleBold.wrap('IDL Command')}: $_thisScript idl [options]

Usage:
${_parser.commands['idl']?.usage}
${ansi.styleBold.wrap('WebIDL Gen')}:
$_thisScript [options]

${ansi.styleBold.wrap('Typescript Gen Command')}: $_thisScript dts <.d.ts file> [options]
If no IDL file is provided, defaults to the WebIDL definitions needed for package:web

Usage:
${_parser.commands['dts']?.usage}''';
${_parser.usage}''';

final _parser = ArgParser()
..addFlag('help', negatable: false, help: 'Show help information')
..addFlag('update', abbr: 'u', help: 'Update npm dependencies')
..addFlag('compile', defaultsTo: true)
..addOption('output',
abbr: 'o',
help: 'Output directory where bindings will be generated to '
'(defaults to `lib/src` in the web package when no IDL file is provided)')
..addMultiOption('input',
abbr: 'i',
help: 'The input IDL file(s) to read and generate bindings for. '
'If not provided, the default WebIDL definitions will be used.')
..addFlag('generate-all',
negatable: false,
help: 'Generate bindings for all IDL definitions, including experimental '
Expand Down
4 changes: 2 additions & 2 deletions web_generator/lib/src/cli.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import 'package:path/path.dart' as p;

final bindingsGeneratorPath = p.fromUri(Platform.script.resolve('../lib/src'));

Future<void> compileDartMain({String? langVersion}) async {
Future<void> compileDartMain({String? langVersion, String? dir}) async {
await runProc(
Platform.executable,
[
Expand All @@ -27,7 +27,7 @@ Future<void> compileDartMain({String? langVersion}) async {
'-o',
'dart_main.js',
],
workingDirectory: bindingsGeneratorPath,
workingDirectory: dir ?? bindingsGeneratorPath,
);
}

Expand Down
55 changes: 41 additions & 14 deletions web_generator/lib/src/dart_main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ void main(List<String> args) async {

if (argResult.wasParsed('idl')) {
await generateIDLBindings(
outputDirectory: argResult['output'] as String,
input: (argResult['input'] as List<String>).isEmpty
? null
: argResult['input'] as Iterable<String>,
output: argResult['output'] as String,
generateAll: argResult['generate-all'] as bool,
languageVersion: Version.parse(languageVersionString),
);
Expand Down Expand Up @@ -64,22 +67,46 @@ Future<void> generateJSInteropBindings({
}

Future<void> generateIDLBindings({
required String outputDirectory,
Iterable<String>? input,
required String output,
required bool generateAll,
required Version languageVersion,
}) async {
const librarySubDir = 'dom';

ensureDirectoryExists('$outputDirectory/$librarySubDir');

final bindings = await generateBindings(packageRoot, librarySubDir,
generateAll: generateAll);
for (var entry in bindings.entries) {
final libraryPath = entry.key;
final library = entry.value;

final contents = _emitLibrary(library, languageVersion).toJS;
fs.writeFileSync('$outputDirectory/$libraryPath'.toJS, contents);
if (input == null) {
// parse dom library as normal
const librarySubDir = 'dom';

ensureDirectoryExists('$output/$librarySubDir');

final bindings = await generateBindings(packageRoot, librarySubDir,
generateAll: generateAll);

for (var entry in bindings.entries) {
final libraryPath = entry.key;
final library = entry.value;

final contents = _emitLibrary(library, languageVersion).toJS;
fs.writeFileSync('$output/$libraryPath'.toJS, contents);
}
} else {
// parse individual files
ensureDirectoryExists(output);

final bindings = await generateBindingsForFiles({
for (final file in input)
file: (fs.readFileSync(
file.toJS, JSReadFileOptions(encoding: 'utf-8'.toJS))
as JSString)
.toDart
}, output);

for (var entry in bindings.entries) {
final libraryPath = entry.key;
final library = entry.value;

final contents = _emitLibrary(library, languageVersion).toJS;
fs.writeFileSync('$output/$libraryPath'.toJS, contents);
}
}
}

Expand Down
25 changes: 23 additions & 2 deletions web_generator/lib/src/generate_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

import 'dart:js_interop';

import 'package:path/path.dart' as p;

import 'js/webidl2.dart' as webidl2;
import 'js/webidl_api.dart' as webidl;
import 'js/webref_css_api.dart';
import 'js/webref_elements_api.dart';
Expand Down Expand Up @@ -74,8 +77,8 @@ Future<TranslationResult> generateBindings(
final cssStyleDeclarations = await _generateCSSStyleDeclarations();
final elementHTMLMap = await _generateElementTagMap();
final translator = Translator(
packageRoot, librarySubDir, cssStyleDeclarations, elementHTMLMap,
generateAll: generateAll);
librarySubDir, cssStyleDeclarations, elementHTMLMap,
generateAll: generateAll, packageRoot: packageRoot);
final array = objectEntries(await idl.parseAll().toDart);
for (var i = 0; i < array.length; i++) {
final entry = array[i] as JSArray<JSAny?>;
Expand All @@ -86,3 +89,21 @@ Future<TranslationResult> generateBindings(
translator.addInterfacesAndNamespaces();
return translator.translate();
}

Future<TranslationResult> generateBindingsForFiles(
Map<String, String> fileContents, String output) async {
// generate CSS style declarations and element tag map incase they are
// needed for the input files.
final cssStyleDeclarations = await _generateCSSStyleDeclarations();
final elementHTMLMap = await _generateElementTagMap();
final translator = Translator(output, cssStyleDeclarations, elementHTMLMap,
generateAll: true, generateForWeb: false);

for (final file in fileContents.entries) {
final ast = webidl2.parse(file.value);
translator.collect(p.basenameWithoutExtension(file.key), ast);
}

translator.addInterfacesAndNamespaces();
return translator.translate();
}
12 changes: 12 additions & 0 deletions web_generator/lib/src/js/webidl2.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2025, 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.
@JS('webidl2')
library;

import 'dart:js_interop';

import 'webidl_api.dart' as idl;

@JS()
external JSArray<idl.Node> parse(String contents);
2 changes: 2 additions & 0 deletions web_generator/lib/src/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { createRequire } from 'module';
import * as css from '@webref/css';
import * as elements from '@webref/elements';
import * as idl from '@webref/idl';
import * as webidl2 from "webidl2";
import * as ts from 'typescript';

const require = createRequire(import.meta.url);
Expand All @@ -19,6 +20,7 @@ globalThis.css = css;
globalThis.elements = elements;
globalThis.fs = fs;
globalThis.idl = idl;
globalThis.webidl2 = webidl2;
globalThis.ts = ts;
globalThis.location = { href: `file://${process.cwd()}/` }

Expand Down
6 changes: 2 additions & 4 deletions web_generator/lib/src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions web_generator/lib/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
"@webref/css": "^6.11.0",
"@webref/elements": "^2.2.2",
"@webref/idl": "^3.43.1",
"typescript": "^5.8.3"
},
"devDependencies": {
"webidl2": "^24.2.2"
"typescript": "^5.8.3",
"webidl2": "^24.4.1"
}
}
Loading