Skip to content

Commit

Permalink
HTTP resources (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford authored Oct 26, 2023
1 parent 1464074 commit 1c04575
Show file tree
Hide file tree
Showing 41 changed files with 923 additions and 645 deletions.
4 changes: 2 additions & 2 deletions crates/js-component-bindgen/src/function_bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ impl Bindgen for FunctionBindgen<'_> {
results.push(format!("variant{}_{}", tmp, i));
}

let expr_to_match = format!("variant{}.tag", tmp);
let expr_to_match = format!("variant{tmp}.tag");

uwriteln!(self.src, "switch ({expr_to_match}) {{");
for (case, (block, block_results)) in variant.cases.iter().zip(blocks) {
Expand All @@ -498,7 +498,7 @@ impl Bindgen for FunctionBindgen<'_> {
self.src,
"default: {{
throw new TypeError('invalid variant specified for {variant_name}');
}}"
}}",
);
uwriteln!(self.src, "}}");
}
Expand Down
92 changes: 38 additions & 54 deletions crates/js-component-bindgen/src/transpile_bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,12 @@ pub fn transpile_bindgen(
translation: component,
component: &component.component,
types,
imports: BTreeMap::new(),
exports: BTreeMap::new(),
imports: Default::default(),
exports: Default::default(),
lowering_options: Default::default(),
imports_resource_map: Default::default(),
exports_resource_map: Default::default(),
defined_resource_classes: Default::default(),
resource_tables_initialized: (0..component.component.num_resource_tables)
.map(|_| false)
.collect(),
Expand Down Expand Up @@ -322,6 +323,7 @@ struct Instantiator<'a, 'b> {
imports: BTreeMap<String, WorldKey>,
imports_resource_map: ResourceMap,
exports_resource_map: ResourceMap,
defined_resource_classes: BTreeSet<String>,
lowering_options:
PrimaryMap<LoweredIndex, (&'a CanonicalOptions, TrampolineIndex, TypeFuncIndex)>,
}
Expand Down Expand Up @@ -1386,31 +1388,23 @@ impl<'a> Instantiator<'a, '_> {
WorldItem::Function(f) => f,
WorldItem::Interface(_) | WorldItem::Type(_) => unreachable!(),
};
let (local_name, existing_resource_def) =
if let FunctionKind::Constructor(tid)
| FunctionKind::Method(tid)
| FunctionKind::Static(tid) = func.kind
{
let resource_id = tid;
let ty = &self.resolve.types[tid];
let resource = ty.name.as_ref().unwrap();
self.gen.local_names.get_or_create(
ResourceInstance {
resource_id,
import: None,
},
&resource.to_upper_camel_case(),
)
} else {
(self.gen.local_names.create_once(export_name), false)
};
let local_name = local_name.to_string();
let local_name = if let FunctionKind::Constructor(resource_id)
| FunctionKind::Method(resource_id)
| FunctionKind::Static(resource_id) = func.kind
{
self.gen.local_names.get(ResourceInstance {
resource_id,
import: None,
})
} else {
self.gen.local_names.create_once(export_name)
}
.to_string();
self.export_bindgen(
&local_name,
def,
options,
func,
existing_resource_def,
export_name,
// exported top-level functions only reference imported resources
false,
Expand Down Expand Up @@ -1447,35 +1441,20 @@ impl<'a> Instantiator<'a, '_> {

let func = &self.resolve.interfaces[id].functions[func_name];

let (local_name, existing_resource_def) =
if let FunctionKind::Constructor(tid)
| FunctionKind::Method(tid)
| FunctionKind::Static(tid) = func.kind
{
let resource_id = tid;
let ty = &self.resolve.types[tid];
let resource = ty.name.as_ref().unwrap();
self.gen.local_names.get_or_create(
ResourceInstance {
resource_id,
import: None,
},
&resource.to_upper_camel_case(),
)
} else {
(self.gen.local_names.create_once(func_name), false)
};

let local_name = local_name.to_string();
self.export_bindgen(
&local_name,
def,
options,
func,
existing_resource_def,
export_name,
true,
);
let local_name = if let FunctionKind::Constructor(resource_id)
| FunctionKind::Method(resource_id)
| FunctionKind::Static(resource_id) = func.kind
{
self.gen.local_names.get(ResourceInstance {
resource_id,
import: None,
})
} else {
self.gen.local_names.create_once(func_name)
}
.to_string();

self.export_bindgen(&local_name, def, options, func, export_name, true);

if let FunctionKind::Constructor(ty)
| FunctionKind::Method(ty)
Expand Down Expand Up @@ -1515,15 +1494,15 @@ impl<'a> Instantiator<'a, '_> {
def: &CoreDef,
options: &CanonicalOptions,
func: &Function,
existing_resource_def: bool,
export_name: &String,
exports_resource_map: bool,
) {
match func.kind {
FunctionKind::Freestanding => uwrite!(self.src.js, "\nfunction {local_name}"),
FunctionKind::Method(_) => {
if !existing_resource_def {
if !self.defined_resource_classes.contains(local_name) {
uwriteln!(self.src.js, "\nclass {local_name} {{}}");
self.defined_resource_classes.insert(local_name.to_string());
}
let method_name = func.item_name().to_lower_camel_case();
uwrite!(
Expand All @@ -1532,8 +1511,9 @@ impl<'a> Instantiator<'a, '_> {
);
}
FunctionKind::Static(_) => {
if !existing_resource_def {
if !self.defined_resource_classes.contains(local_name) {
uwriteln!(self.src.js, "\nclass {local_name} {{}}");
self.defined_resource_classes.insert(local_name.to_string());
}
let method_name = func.item_name().to_lower_camel_case();
uwrite!(
Expand All @@ -1542,6 +1522,9 @@ impl<'a> Instantiator<'a, '_> {
);
}
FunctionKind::Constructor(ty) => {
if self.defined_resource_classes.contains(local_name) {
panic!("Internal error: Resource constructor must be defined before other methods and statics");
}
let ty = &self.resolve.types[ty];
let name = ty.name.as_ref().unwrap();
if name.to_upper_camel_case() == local_name {
Expand All @@ -1560,6 +1543,7 @@ impl<'a> Instantiator<'a, '_> {
name.to_upper_camel_case()
);
}
self.defined_resource_classes.insert(local_name.to_string());
}
}
let callee = self.core_def(def);
Expand Down
29 changes: 25 additions & 4 deletions crates/js-component-bindgen/src/ts_bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use heck::*;
use std::collections::btree_map::Entry;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fmt::Write;
use std::mem;
use wit_parser::*;

struct TsBindgen {
Expand Down Expand Up @@ -403,6 +402,20 @@ impl TsBindgen {
for (_, func) in resolve.interfaces[id].functions.iter() {
gen.ts_func(func, false, true);
}
for (_, ty) in resolve.interfaces[id].types.iter() {
let ty = &resolve.types[*ty];
match ty.kind {
TypeDefKind::Resource => {
let resource = ty.name.as_ref().unwrap();
if !gen.resources.contains_key(resource) {
uwriteln!(gen.src, "export {{ {} }};", resource.to_upper_camel_case());
gen.resources
.insert(resource.to_string(), TsInterface::new(resolve));
}
}
_ => {}
}
}
uwriteln!(gen.src, "}}");

gen.types(id);
Expand Down Expand Up @@ -677,11 +690,15 @@ impl<'a> TsInterface<'a> {
}

fn post_types(&mut self) {
if mem::take(&mut self.needs_ty_option) {
let needs_ty_option =
self.needs_ty_option || self.resources.iter().any(|(_, r)| r.needs_ty_option);
let needs_ty_result =
self.needs_ty_result || self.resources.iter().any(|(_, r)| r.needs_ty_result);
if needs_ty_option {
self.src
.push_str("export type Option<T> = { tag: 'none' } | { tag: 'some', val: T };\n");
}
if mem::take(&mut self.needs_ty_result) {
if needs_ty_result {
self.src.push_str(
"export type Result<T, E> = { tag: 'ok', val: T } | { tag: 'err', val: E };\n",
);
Expand Down Expand Up @@ -883,7 +900,11 @@ impl<'a> TsInterface<'a> {
}

fn interface_goal_name(iface_name: &str) -> String {
iface_name
let iface_name_sans_version = match iface_name.find('@') {
Some(version_idx) => &iface_name[0..version_idx],
None => iface_name.as_ref(),
};
iface_name_sans_version
.replace('/', "-")
.replace(':', "-")
.to_kebab_case()
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"terser": "^5.16.1"
},
"devDependencies": {
"@bytecodealliance/componentize-js": "^0.3.0",
"@bytecodealliance/componentize-js": "^0.4.0",
"@types/node": "^18.11.17",
"@typescript-eslint/eslint-plugin": "^5.41.0",
"@typescript-eslint/parser": "^5.41.0",
Expand Down
39 changes: 0 additions & 39 deletions packages/preview2-shim/lib/browser/io.js

This file was deleted.

4 changes: 2 additions & 2 deletions packages/preview2-shim/lib/common/io.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Error {
* skip?: (len: BigInt) => BigInt,
* blockingSkip?: (len: BigInt) => BigInt,
* subscribe: () => void,
* drop: () => void,
* drop?: () => void,
* }} InputStreamHandler
*
* @typedef {{
Expand All @@ -32,7 +32,7 @@ class Error {
* blockingSplice?: (src: InputStream, len: BigInt) => BigInt,
* forward?: (src: InputStream) => void,
* subscribe?: () => void,
* drop: () => void,
* drop?: () => void,
* }} OutputStreamHandler
*
**/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { runAsWorker } from "./synckit/index.js";
import { runAsWorker } from "../synckit/index.js";

/**
* @param {import("../../types/interfaces/wasi-http-types").Request} req
Expand Down
Loading

0 comments on commit 1c04575

Please sign in to comment.