🚨 Very experimental 🚨
Type-safe access to DOM and other Web APIs from Swift, using @webref/idl package to generate the bindings and JavaScriptKit to enable access to the actual objects.
Access the DOM and other Web APIs from Swift! (Very much a WIP)
License: MIT License
🚨 Very experimental 🚨
Type-safe access to DOM and other Web APIs from Swift, using @webref/idl package to generate the bindings and JavaScriptKit to enable access to the actual objects.
It looks we're going to host not only DOM APIs here, but all Web APIs. Maybe let's rename the library before we've tagged the first release, to avoid the confusion?
Subscript getters/setters are represented as separate nodes in WebIDL, so we’ll need to do a step to merge them before attempting to print them (since Swift requires that the getter and setter for a subscript be colocated)
For a related example, see AsyncOperation
, which wraps a single IDLOperation
to emit both a JSPromise
-returning and an async
version of the method.
Also, support for deleters should be added. Swift doesn’t have a concept of a deleter, so I guess the best approach would be to define a removeValue(forKey:)
method, just like Dictionary
?
The spec defines these without specific method names so we’re technically free to do anything we like (I assume they should conform to Collection
or similar), although it does define how JS interprets this declaration.
I want to use custom elements.
https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements
Is there any way to do this?
If the WebAPIKit not support this yet, is there any way to do this with JavascriptKit?
It would be great to have some functions added to quickly convert from BufferArray to Foundation.Data and back.
These are a Cursed Object in the WebIDL spec (https://webidl.spec.whatwg.org/#idl-callback-interfaces), and they’re essentially shorthand for a union between a function/closure type and an object with a property matching that function type. They are unfortunately important because EventListener
is a callback interface (although NodeFilter
and XPathNSResolver
are also a callback interface, they are less commonly used). This PR depends on #32, probably.
Playing with the library a bit more, I think it would be great to split it into separate targets and products, if possible. As an example, people who don't need WebGL don't need to build WebGL wrappers, but I think it still makes sense to provide them.
IDK if WebIDL specifies dependencies between their "modules", so maybe we'd need to hardcode those on our side for things to work?
Now if I do this
let shadowRoot = rootView.attachShadow(init: .init(mode: .open, delegatesFocus: true, slotAssignment: .manual))
shadowRoot.ownerDocument?.body?.appendChild(node: childNode)
The shadow root is open correct, but the childNode wound't add to it.
But if I change the second line to
shadowRoot.jsValue.appendChild(node.jsValue)
It would work.
The appendChild(node: Node)
for Node
return type should be same as the child, not the parent. Now if you use the div element to add a span, it would cause error. I'm currently using a method below instead.
func addNode<T: Node>(_ node: T) -> T {
let result = self.jsValue.appendChild(node.jsValue)
return T.init(from: result)!
}
Currently, WebGL 1.0, WebGL 2.0, and WebGPU can't be split into separate modules as targets, as enum RenderingContext
wraps all available context types and needs to have all of them in scope.
If RenderingContext
were a protocol, we could declare it in some "base" module and move GPUCanvasContext
, WebGLRenderingContext
, and WebGL2RenderingContext
to their own respective modules adding a conformance on them to that protocol.
I also thought about subclassing, but that clearly won't work due to the lack of multiple class inheritance. These types already inherit from JSBridgedClass
, and protocols are the suggested instruments of achieving multiple inheritance in Swift.
With Tokamak you'll have to use the Fetch API, and there are no SwiftWasm bindings for it yet, as far as I'm aware. I guess we will have some in the near future as a part of the DOMKit library, but my understanding is that it's not there yet, and is not a part of WebIDL declarations included there, maybe @j-f1 could clarify? Also, bear in mind that
fetch
returns aPromise
object, and the API for it is still being developed in swiftwasm/JavaScriptKit#62. Closure-based APIs in SwiftWasm are not very trivial to work with, as you have to be aware of the lifetime of your closure instances and manually release them. This is an inherent problem caused by the differences in how JavaScript (garbage collection) and Swift (reference counting) allocate memory for closures and their context.
Indeed —
fetch
is a separate spec that would have to be integrated. I’m not sure how the original maintainers got the.webidl
files out of the specs, and I would like to follow the same process for fetch.
Yes, it would be great to know where the WebIDL specs come from, as I'd like many more APIs covered eventually, IndexedDB, WebGL (WebIDL for this one is maintained together with the human readable text spec apparently), Web Animations obviously, and whatever comes next that users would be interested in.
I’m guessing they were extracted from the .bs
files by looking for the <pre class=idl>
blocks. @Unkaputtbar @PSchmiedmayer do you have any more information on how this was done?
This is currently only used by one type, TrustedTypePolicyFactory
. …looking at this again, I'm not sure what exactly this needs in terms of code changes. I think it has something to do with TrustedTypePolicyOptions
.
FrozenArray
s are essentially readonly arrays in Swift.
ObservableArray
s seem to have an identical API to a regular array, except that the spec can define custom behaviors when the array is modified. So I’m not sure whether we need to do anything special in Swift to handle this.
These four symbols override something from their parent in an incompatible way. I think the best way forward would be to manually define extensions to those types using a slightly different name, but I’m not sure.
extension HTMLElement: ElementCSSInlineStyle {}
should be add to the library. Now the ElementCSSInlineStyle is almost useless.
They all look like they can be made into class methods, so I’m not sure why that isn’t the case.
These symbols are currently stripped from the emitted code. I think this will need generated code similar to the ClosureAttribute*
types.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.