///|
const WPT_INTERFACES_URL = "https://wpt.live/interfaces/"
///|
const FIXTURE_DIRECTORY = "parser/fixtures/wpt"
///|
const GENERATED_TEST_FILE = "parser/wpt_generated_test.mbt"
///|
struct WptFile {
name : String
}
///|
fn exclude_wpt_idl(name : StringView) -> Bool {
name is "webrtc-ice.idl" || name is "mediacapture-surface-control.idl"
}
///|
async fn fetch_text(url : String) -> String {
let (response, body) = @http.get(url)
if response.code != 200 {
fail("GET " + url + " returned HTTP " + response.code.to_string())
}
body.text()
}
///|
const IDL_LINK = re"href=\"([^\"]+[.]idl)\""
///|
async fn fetch_wpt_idl_files() -> Array[WptFile] {
let listing = fetch_text(WPT_INTERFACES_URL)
let files : Array[WptFile] = []
let mut remaining : StringView = listing
while IDL_LINK.execute(remaining) is Some(link) {
guard link.group(1) is Some(name) else {
remaining = link.after()
continue
}
if !exclude_wpt_idl(name) {
files.push(WptFile::{ name: name.to_owned() })
}
remaining = link.after()
}
files.sort_by((a, b) => a.name.compare(b.name))
files
}
///|
fn generate_test_source(files : ArrayView[WptFile]) -> String {
let mut output =
#|/// Auto-generated by cmd/build_idl_tests. Do not edit manually.
#|/// Each WPT IDL fixture has its own independently filterable test.
#|
#|///|
#|async fn parse_wpt_idl_fixture(file : String) -> Unit {
#| let source = @fs.read_file("parser/fixtures/wpt/" + file).text()
#| let tokens = @lexer.tokenize(source)
#| let (_, rest) = parse(tokens.view())
#| if rest is [(_, text), ..] {
#| fail(
#| file + ": first unconsumed token '" + text.to_owned() + "' (" +
#| rest.length().to_string() + " tokens remaining)",
#| )
#| }
#|}
#|
for file in files {
output = output +
"///|\nasync test \"WPT: " +
file.name.escape(quote=false) +
"\" {\n" +
" parse_wpt_idl_fixture(" +
file.name.escape() +
")\n" +
"}\n\n"
}
output
}
///|
fn generate_readme(count : Int) -> String {
let output =
$|# WPT Web IDL fixtures
$|
$|These files are copied byte-for-byte from interfaces/*.idl in the
$|web-platform-tests/wpt repository:
$|https://github.com/web-platform-tests/wpt
$|
$|- Source: https://wpt.live/interfaces/
$|- Files: \{count}, including *.tentative.idl
$|- Excluded: webrtc-ice.idl and mediacapture-surface-control.idl because
$| they contain constructors in partial interfaces, which Web IDL forbids.
$|
$|Run moon run cmd/build_idl_tests to replace the fixtures from WPT Live
$|and regenerate parser/wpt_generated_test.mbt.
$|
$|Do not edit the IDL fixtures locally.
output
}
///|
async fn remove_stale_idl_files() -> Unit {
if @fs.exists(FIXTURE_DIRECTORY) {
for file in @fs.readdir(FIXTURE_DIRECTORY) {
if file.has_suffix(".idl") {
@fs.remove(FIXTURE_DIRECTORY + "/" + file)
}
}
} else {
@fs.mkdir(FIXTURE_DIRECTORY, recursive=true)
}
}
///|
async fn main {
println("Fetching the latest WPT Web IDL corpus...")
let files = fetch_wpt_idl_files()
remove_stale_idl_files()
let downloads : Array[async () -> Unit] = files.mapi((index, file) => {
async fn() {
let source = fetch_text(WPT_INTERFACES_URL + file.name)
@fs.write_file(
FIXTURE_DIRECTORY + "/" + file.name,
source,
create_mode=@fs.CreateMode::CreateOrTruncate,
)
println(
"[" +
(index + 1).to_string() +
"/" +
files.length().to_string() +
"] " +
file.name,
)
}
})
ignore(@async.all(downloads, max_concurrent=16))
@fs.write_file(
GENERATED_TEST_FILE,
generate_test_source(files),
create_mode=@fs.CreateMode::CreateOrTruncate,
)
@fs.write_file(
FIXTURE_DIRECTORY + "/README.md",
generate_readme(files.length()),
create_mode=@fs.CreateMode::CreateOrTruncate,
)
println("Generated " + files.length().to_string() + " WPT IDL tests")
}