Skip to content

Commit

Permalink
idea
Browse files Browse the repository at this point in the history
  • Loading branch information
jcbhmr committed Jul 3, 2023
1 parent 5d82f78 commit 8109a57
Show file tree
Hide file tree
Showing 25 changed files with 236 additions and 227 deletions.
49 changes: 47 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
# webidl
# WebIDL helpers for JavaScript

📚 WebIDL infrastructure for making JavaScript ↔️ JavaScript bindings
📚 [WebIDL] infrastructure for making JavaScript ↔️ JavaScript bindings

<div align="center">

![]()

</div>

## Installation

```sh
npm install @webfill/webidl
```

## Usage

```js
import { bindInterface, defineOperation, types } from "@webfill/webidl";

class Dog {
bark() {
console.log("woof");
}
eat(food) {
console.log(`eating ${food}`);
}
}
Dog = bindInterface(Dog, "Dog");
defineOperation(Dog.prototype, "bark", [], types.undefined)
defineOperation(Dog.prototype, "eat", [types.DOMString], types.undefined);

const dog = new Dog();
//=> Uncaught TypeError: Illegal constructor

const dog = Object.create(Dog.prototype);
dog.bark();
//=> 'woof'

dog.eat();
//=> Uncaught TypeError: Failed to execute 'eat' on 'Dog': 1 argument required, but only 0 present.

dog.eat("🥩");
//=> 'eating 🥩'
```

[WebIDL]: https://webidl.spec.whatwg.org/
4 changes: 2 additions & 2 deletions package-lock.json

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

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
"type": "module",
"exports": {
".": "./dist/index.js",
"./DOMException.js": {
"deno": "./src/DOMException.js",
"bun": "./src/DOMException.js",
"node": "./src/DOMException-node.js",
"default": "./src/DOMException.js"
},
"./*.js": "./dist/*.js",
"./internal/*": null
},
Expand Down
9 changes: 9 additions & 0 deletions src/DOMException-node-16.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type {typeof globalThis.DOMException} */
let DOMException;
try {
atob(1);
} catch (error) {
DOMException = error.constructor;
}

export default DOMException;
9 changes: 9 additions & 0 deletions src/DOMException-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type {typeof globalThis.DOMException} */
let DOMException;
if (process.version.startsWith("v16")) {
({ default: DOMException } = await import("./DOMException-node-16.js"));
} else {
DOMException = globalThis.DOMException;
}

export default DOMException;
1 change: 1 addition & 0 deletions src/DOMException.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default DOMException;
31 changes: 31 additions & 0 deletions src/bindInterface.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @template {{ new (...a: any[]): any }} T
* @param {T} Class
* @param {string} name
* @param {boolean} [constructable]
* @returns {T}
*/
export default function bindInterface(Class, name, constructable = undefined) {
Object.defineProperty(Class, "name", { value: name, configurable: true });
Object.defineProperty(Class.prototype, Symbol.toStringTag, {
value: name,
configurable: true,
});

if (constructable == null) {
constructable = /\Wconstructor\(/.test(
Function.prototype.toString.call(Class)
);
}

if (!constructable) {
Object.defineProperty(Class, "length", { value: 0, configurable: true });
Class = new Proxy(Class, {
construct() {
throw new TypeError(`Illegal constructor`);
},
});
}

return Class;
}
32 changes: 32 additions & 0 deletions src/defineAttribute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @template {object} O
* @template {keyof O | string} N
* @template {{ from(x: unknown): any }[]} T
* @param {O} object
* @param {N} name
* @param {T} [attrType]
* @returns {O}
*/
export default function defineAttribute(object, name, attrType = undefined) {
const { get, set } = Object.getOwnPropertyDescriptor(object, name);
Object.defineProperty(object, name, {
get() {
let x = get.call(this);
if (attrType) {
x = attrType.from(x);
}
return x;
},
...(set && {
set(x) {
if (attrType) {
x = attrType.from(x);
}
set.call(this, x);
},
}),
enumerable: true,
configurable: true,
});
return object;
}
17 changes: 17 additions & 0 deletions src/defineExtendedAttribute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @template {object} O
* @param {O} object
* @param {keyof O | string} name
* @param {(t: "descriptor", d: PropertyDescriptor) => PropertyDescriptor | null | undefined} ExtendedAttribute
* @returns {O}
*/
export default function defineExtendedAttribute(
object,
name,
ExtendedAttribute
) {
let d = Object.getOwnPropertyDescriptor(object, name);
d = ExtendedAttribute("descriptor", d) ?? d;
Object.defineProperty(object, name, d);
return object;
}
41 changes: 41 additions & 0 deletions src/defineOperation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* @template {object} O
* @template {keyof O | string} N
* @template {{ from(x: unknown): any }[]} A
* @template {{ from(x: any): any }} R
* @param {O} object
* @param {N} name
* @param {A} [argTypes]
* @param {R} [returnType]
* @returns {O}
*/
export default function defineOperation(
object,
name,
argTypes = undefined,
returnType = undefined
) {
const original = object[name];
const { value } = {
value() {
if (argTypes) {
for (const [i, argType] of argTypes.entries()) {
arguments[i] = argType.from(arguments[i]);
}
}
let result = original.apply(this, arguments);
if (returnType) {
result = returnType.from(result);
}
return result;
},
};
Object.defineProperties(value, Object.getOwnPropertyDescriptors(original));
Object.defineProperty(object, name, {
value,
writable: true,
enumerable: true,
configurable: true,
});
return object;
}
20 changes: 20 additions & 0 deletions src/extended-attributes/Global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @param {string | string[]} nameOrNames
* @returns {(t: "value", n: string, v: any) => void}
*/
export default function Global(nameOrNames) {
const names = Array.isArray(nameOrNames) ? nameOrNames : [nameOrNames];
return (t, n, v) => {
for (const name of names) {
if (isInstanceOf(globalThis, name)) {
Object.defineProperty(globalThis, n, {
value: v,
writable: true,
configurable: true,
enumerable: true,
});
return;
}
}
};
}
2 changes: 1 addition & 1 deletion src/index.ts → src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * as types from "./types/index.js";
export { default as interface_ } from "./interface_.js";
export { default as interface_ } from "./interface.js";
export { default as operation } from "./operation.js";
23 changes: 0 additions & 23 deletions src/interface_.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/internal/REF-type-fest/README.md

This file was deleted.

20 changes: 0 additions & 20 deletions src/internal/REF-type-fest/basic.d.ts

This file was deleted.

8 changes: 8 additions & 0 deletions src/internal/isInstanceOf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export function isInstanceOf(value, classOrClassName) {
for (let p = value; p; p = Object.getPrototypeOf(p)) {
if (Object.prototype.toString.call(p).slice(8, -1) === classOrClassName) {
return true;
}
}
return false;
}
34 changes: 0 additions & 34 deletions src/operation.ts

This file was deleted.

11 changes: 11 additions & 0 deletions src/types/DOMString.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/** @typedef {string} DOMString */
const DOMString = {
/**
* @param {unknown} x
* @returns {DOMString}
*/
from(x) {
return `${x}`;
},
};
export default DOMString;
8 changes: 0 additions & 8 deletions src/types/DOMString.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/types/index.ts → src/types/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { default as DOMString } from "./DOMString.js";
export { default as long } from "./long.js";
export { default as undefined_ } from "./undefined_.js";
export { default as undefined } from "./undefined.js";
1 change: 0 additions & 1 deletion src/types/long.ts → src/types/long.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ const long = {
return Math.trunc(x);
},
};

export default long;
1 change: 0 additions & 1 deletion src/types/undefined_.ts → src/types/undefined.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ const undefined_ = {
return undefined;
},
};

export default undefined_;
7 changes: 0 additions & 7 deletions test/types/index.test.ts

This file was deleted.

Loading

0 comments on commit 8109a57

Please sign in to comment.