From 6bc4f6a9c26bc8a5bd6e37337b2a1ca67de08de8 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Thu, 17 Oct 2024 14:55:09 -0400 Subject: [PATCH 01/23] Start of io typings work --- examples/io/tcp/websocketclient/config.js | 22 ++++++++- examples/io/tcp/websocketclient/manifest.json | 1 + .../manifest_websocketclient.json | 4 +- examples/manifest_typings.json | 7 ++- typings/embedded_io/socket/tcp.d.ts | 4 +- typings/embedded_io/socket/{ => tcp}/tls.d.ts | 6 +-- .../embedded_network/dns/resolver/udp.d.ts | 10 ++-- .../embedded_network/websocket/client.d.ts | 49 +++++++++++++++++++ typings/embedded_provider/builtin.d.ts | 12 +++++ 9 files changed, 102 insertions(+), 13 deletions(-) rename typings/embedded_io/socket/{ => tcp}/tls.d.ts (69%) create mode 100644 typings/embedded_network/websocket/client.d.ts diff --git a/examples/io/tcp/websocketclient/config.js b/examples/io/tcp/websocketclient/config.js index 3bf2cd8583..5e58e0755f 100644 --- a/examples/io/tcp/websocketclient/config.js +++ b/examples/io/tcp/websocketclient/config.js @@ -1,6 +1,7 @@ import "system" // system initializes globalThis.device. this ensures it runs before this module. import TCP from "embedded:io/socket/tcp"; +import TLSSocket from 'embedded:io/socket/tcp/tls'; import UDP from "embedded:io/socket/udp"; import Resolver from "embedded:network/dns/resolver/udp"; @@ -9,7 +10,8 @@ import WebSocketClient from "embedded:network/websocket/client"; const dns = { io: Resolver, servers: [ - "1.1.1.1", //... + "1.1.1.1", + "8.8.8.8" ], socket: { io: UDP, @@ -20,12 +22,28 @@ globalThis.device = Object.freeze({ network: { ...globalThis.device?.network, ws: { + client: { + dns, + socket: { + io: TCP + } + }, io: WebSocketClient, + // todo: are these legacy? dns, socket: { io: TCP, - }, + } }, + wss: { + client: { + dns, + socket: { + io: TLSSocket + } + }, + io: WebSocketClient + } }, }, true); diff --git a/examples/io/tcp/websocketclient/manifest.json b/examples/io/tcp/websocketclient/manifest.json index 6038012185..c1a0a9e068 100644 --- a/examples/io/tcp/websocketclient/manifest.json +++ b/examples/io/tcp/websocketclient/manifest.json @@ -3,6 +3,7 @@ "$(MODDABLE)/examples/manifest_base.json", "$(MODDABLE)/examples/manifest_net.json", "$(MODDABLE)/modules/io/manifest.json", + "$(MODDABLE)examples/io/tcp/tlssocket/manifest.json", "./manifest_websocketclient.json" ], "modules": { diff --git a/examples/io/tcp/websocketclient/manifest_websocketclient.json b/examples/io/tcp/websocketclient/manifest_websocketclient.json index 8ca27bee0a..ab24d5ecc8 100644 --- a/examples/io/tcp/websocketclient/manifest_websocketclient.json +++ b/examples/io/tcp/websocketclient/manifest_websocketclient.json @@ -2,7 +2,9 @@ "include": [ "$(MODDABLE)/modules/io/manifest.json", "$(MODDABLE)/modules/data/text/decoder/manifest.json", - "$(MODDABLE)/examples/io/udp/dns/manifest_dns.json" + "$(MODDABLE)/examples/io/udp/dns/manifest_dns.json", + "$(MODDABLE)/examples/io/tcp/tlssocket/manifest.json" + ], "modules": { "*": [ diff --git a/examples/manifest_typings.json b/examples/manifest_typings.json index 97a12fb9e3..276139e4b4 100644 --- a/examples/manifest_typings.json +++ b/examples/manifest_typings.json @@ -33,6 +33,9 @@ "embedded:io/socket/*": [ "$(TYPINGS)/embedded_io/socket/*" ], + "embedded:io/socket/tcp/*": [ + "$(TYPINGS)/embedded_io/socket/tcp/*" + ], "embedded:network/http/*": [ "$(TYPINGS)/embedded_network/http/*" ], @@ -42,8 +45,8 @@ "embedded:network/dns/resolver/*": [ "$(TYPINGS)/embedded_network/dns/resolver/*" ], - "embedded:network/*": [ - "$(TYPINGS)/embedded_network/*" + "embedded:network/websocket/*": [ + "$(TYPINGS)/embedded_network/websocket/*" ], "mqtt/js": [ "$(TYPINGS)/mqtt/js" diff --git a/typings/embedded_io/socket/tcp.d.ts b/typings/embedded_io/socket/tcp.d.ts index 71b651ef32..2a28795a19 100644 --- a/typings/embedded_io/socket/tcp.d.ts +++ b/typings/embedded_io/socket/tcp.d.ts @@ -20,7 +20,7 @@ declare module "embedded:io/socket/tcp" { import type { Buffer } from "embedded:io/_common"; - export type Options = ((({ + export type TCPSocketOptions = ((({ address: string; } | { host: string; @@ -38,7 +38,7 @@ declare module "embedded:io/socket/tcp" { }; export default class TCP { - constructor(options: Options) + constructor(options: TCPSocketOptions) readonly remoteAddress: string | undefined; readonly remotePort: number | undefined; read(byteLength?: number): number | ArrayBuffer; diff --git a/typings/embedded_io/socket/tls.d.ts b/typings/embedded_io/socket/tcp/tls.d.ts similarity index 69% rename from typings/embedded_io/socket/tls.d.ts rename to typings/embedded_io/socket/tcp/tls.d.ts index f4a6134d21..0c8d53967b 100644 --- a/typings/embedded_io/socket/tls.d.ts +++ b/typings/embedded_io/socket/tcp/tls.d.ts @@ -1,11 +1,11 @@ declare module "embedded:io/socket/tcp/tls" { - import { Options as TCPOptions } from "embedded:io/socket/tcp" - export type Options = TCPOptions & { + import { TCPSocketOptions as TCPOptions } from "embedded:io/socket/tcp" + export type TLSSocketOptions = TCPOptions & { host: string secure: Record // should be called "tls" according to std? } export default class TLSSocket { - constructor(options: Options) + constructor(options: TLSSocketOptions) close(): undefined read(count: number|ArrayBufferLike) : undefined|ArrayBufferLike write(buffer: ArrayBufferLike) : number diff --git a/typings/embedded_network/dns/resolver/udp.d.ts b/typings/embedded_network/dns/resolver/udp.d.ts index b77b60d992..f554acf3dc 100644 --- a/typings/embedded_network/dns/resolver/udp.d.ts +++ b/typings/embedded_network/dns/resolver/udp.d.ts @@ -20,16 +20,20 @@ declare module "embedded:network/dns/resolver/udp" { - interface Options { + export interface DNSUDPOptions { + http: never; + servers: string[]; + } + interface ResolveOptions { host: string onResolved: ((host:string, address:any) => null) onError: ((host:string) => null) } class Resolver { - constructor(options: Record) + constructor(options: DNSUDPOptions) close(): void - resolve(options: Options): void + resolve(options: ResolveOptions): void } diff --git a/typings/embedded_network/websocket/client.d.ts b/typings/embedded_network/websocket/client.d.ts new file mode 100644 index 0000000000..07bf4cc18d --- /dev/null +++ b/typings/embedded_network/websocket/client.d.ts @@ -0,0 +1,49 @@ +declare module 'embedded:network/websocket/client' { + import type { DNSUDPOptions } from 'embedded:network/dns/resolver/udp'; + import type { Buffer } from 'embedded:io/_common'; + import type TCP from 'embedded:io/socket/tcp'; + import type { TCPSocketOptions } from 'embedded:io/socket/tcp'; + import type TLSSocket from 'embedded:io/socket/tcp/tls'; + import type { TLSSocketOptions } from 'embedded:io/socket/tcp/tls'; + + interface WebSocketClientReadableOptions { + more: boolean; + binary: boolean; + } + + export interface WebSocketClientWriteOptions { + binary?: boolean; + more?: boolean; + opcode?: WebSocketClientOpcode; + } + + type WebSocketClientOpcode = 1 | 2 | 8 | 9 | 10; + + interface WebSocketClientOptions { + attach?: TCP | TLSSocket; + socket?: TCPSocketOptions | TLSSocketOptions; + host?: string; + port?: number; + protocol?: string; + headers?: Map; + dns?: DNSUDPOptions; // spec says required, but when using attach it appears to be optional? + onReadable?: (count: number, options?: WebSocketClientReadableOptions) => void; + onWritable?: (count: number) => void; + onControl?: (opcode: WebSocketClientOpcode, buffer: Uint8Array) => void; // should this be ArrayBuffer? + onClose?: () => void; + onError?: () => void; + } + + export default class WebSocketClient { + constructor(options: WebSocketClientOptions); + close(): void; + read(count?: number): ArrayBuffer; + write(message: Buffer, options?: WebSocketClientWriteOptions): number; + + static readonly text: 1; + static readonly binary: 2; + static readonly close: 8; + static readonly ping: 9; + static readonly pong: 10; + } +} diff --git a/typings/embedded_provider/builtin.d.ts b/typings/embedded_provider/builtin.d.ts index ea56a861b6..0948bd816a 100644 --- a/typings/embedded_provider/builtin.d.ts +++ b/typings/embedded_provider/builtin.d.ts @@ -29,6 +29,8 @@ declare module "embedded:provider/builtin" { import SMBus from "embedded:io/smbus"; import SPI from "embedded:io/spi"; import Serial from "embedded:io/serial"; + import type WebSocketClient from 'embedded:network/websocket/client'; + import type { WebSocketClientOptions } from 'embedded:network/websocket/client'; import type { PinSpecifier } from "embedded:io/_common"; const device: { io: { @@ -52,6 +54,16 @@ declare module "embedded:provider/builtin" { SPI: { default: ConstructorParameters[0] }; Serial: { default: ConstructorParameters[0] }; pin: { [name: string]: PinSpecifier }; + network: { + ws: { + io: typeof WebSocketClient; + client: WebSocketClientOptions; + } + wss: { + io: typeof WebSocketClient; + client: WebSocketClientOptions; + } + }; }; export default device; } From f3c862bf74f05fcbf3f78b91cd966f88aa1c4689 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sat, 19 Oct 2024 08:22:25 -0400 Subject: [PATCH 02/23] Adjust namespace for 'config' to `websocketclient/config` --- examples/io/tcp/websocketclient/manifest_websocketclient.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/io/tcp/websocketclient/manifest_websocketclient.json b/examples/io/tcp/websocketclient/manifest_websocketclient.json index ab24d5ecc8..a38b0fead8 100644 --- a/examples/io/tcp/websocketclient/manifest_websocketclient.json +++ b/examples/io/tcp/websocketclient/manifest_websocketclient.json @@ -8,13 +8,13 @@ ], "modules": { "*": [ - "./config", "$(MODULES)/data/logical/*" ], + "websocketclient/config": "./config", "embedded:network/websocket/client": "./websocketclient" }, "preload": [ - "config", + "websocketclient/config", "embedded:network/websocket/client", "logical" ] From 2fe80d718ff6d91fc47669438440f29b091d9965 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sat, 19 Oct 2024 15:20:31 -0400 Subject: [PATCH 03/23] Revert config.js --- examples/io/tcp/websocketclient/config.js | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/examples/io/tcp/websocketclient/config.js b/examples/io/tcp/websocketclient/config.js index 5e58e0755f..3bf2cd8583 100644 --- a/examples/io/tcp/websocketclient/config.js +++ b/examples/io/tcp/websocketclient/config.js @@ -1,7 +1,6 @@ import "system" // system initializes globalThis.device. this ensures it runs before this module. import TCP from "embedded:io/socket/tcp"; -import TLSSocket from 'embedded:io/socket/tcp/tls'; import UDP from "embedded:io/socket/udp"; import Resolver from "embedded:network/dns/resolver/udp"; @@ -10,8 +9,7 @@ import WebSocketClient from "embedded:network/websocket/client"; const dns = { io: Resolver, servers: [ - "1.1.1.1", - "8.8.8.8" + "1.1.1.1", //... ], socket: { io: UDP, @@ -22,28 +20,12 @@ globalThis.device = Object.freeze({ network: { ...globalThis.device?.network, ws: { - client: { - dns, - socket: { - io: TCP - } - }, io: WebSocketClient, - // todo: are these legacy? dns, socket: { io: TCP, - } + }, }, - wss: { - client: { - dns, - socket: { - io: TLSSocket - } - }, - io: WebSocketClient - } }, }, true); From 65d177ec6cf1e0b32db1b862c593b55d8f3b8d3b Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sat, 19 Oct 2024 15:23:16 -0400 Subject: [PATCH 04/23] Reverse webclient manfiest --- examples/io/tcp/websocketclient/manifest.json | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/io/tcp/websocketclient/manifest.json b/examples/io/tcp/websocketclient/manifest.json index c1a0a9e068..6038012185 100644 --- a/examples/io/tcp/websocketclient/manifest.json +++ b/examples/io/tcp/websocketclient/manifest.json @@ -3,7 +3,6 @@ "$(MODDABLE)/examples/manifest_base.json", "$(MODDABLE)/examples/manifest_net.json", "$(MODDABLE)/modules/io/manifest.json", - "$(MODDABLE)examples/io/tcp/tlssocket/manifest.json", "./manifest_websocketclient.json" ], "modules": { From 201906aaf57c44c8e362b89666bcb687f0905811 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sat, 19 Oct 2024 15:25:05 -0400 Subject: [PATCH 05/23] Revert TLS include --- examples/io/tcp/websocketclient/manifest_websocketclient.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/io/tcp/websocketclient/manifest_websocketclient.json b/examples/io/tcp/websocketclient/manifest_websocketclient.json index a38b0fead8..982ec90472 100644 --- a/examples/io/tcp/websocketclient/manifest_websocketclient.json +++ b/examples/io/tcp/websocketclient/manifest_websocketclient.json @@ -2,9 +2,7 @@ "include": [ "$(MODDABLE)/modules/io/manifest.json", "$(MODDABLE)/modules/data/text/decoder/manifest.json", - "$(MODDABLE)/examples/io/udp/dns/manifest_dns.json", - "$(MODDABLE)/examples/io/tcp/tlssocket/manifest.json" - + "$(MODDABLE)/examples/io/udp/dns/manifest_dns.json" ], "modules": { "*": [ From 9a3aa330f53b21a9c8a531a204b72881d638eba4 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sat, 19 Oct 2024 18:20:04 -0400 Subject: [PATCH 06/23] Define Device into global namespace to allow augmentation; have WebSocket extend Device; improvements overall on types --- typings/embedded_io/socket/tcp.d.ts | 91 ++++++++++--------- typings/embedded_io/socket/tcp/tls.d.ts | 31 ++++--- typings/embedded_io/socket/udp.d.ts | 37 +++++--- .../embedded_network/dns/resolver/udp.d.ts | 22 +++-- .../websocket/client-device.d.ts | 22 +++++ .../embedded_network/websocket/client.d.ts | 21 +++-- typings/embedded_provider/builtin-global.d.ts | 56 ++++++++++++ typings/embedded_provider/builtin.d.ts | 48 +--------- typings/global.d.ts | 5 +- 9 files changed, 192 insertions(+), 141 deletions(-) create mode 100644 typings/embedded_network/websocket/client-device.d.ts create mode 100644 typings/embedded_provider/builtin-global.d.ts diff --git a/typings/embedded_io/socket/tcp.d.ts b/typings/embedded_io/socket/tcp.d.ts index 2a28795a19..6f003127ea 100644 --- a/typings/embedded_io/socket/tcp.d.ts +++ b/typings/embedded_io/socket/tcp.d.ts @@ -1,51 +1,54 @@ /* -* Copyright (c) 2022 Shinya Ishikawa -* -* This file is part of the Moddable SDK Tools. -* -* The Moddable SDK Tools is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* The Moddable SDK Tools is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with the Moddable SDK Tools. If not, see . -* -*/ + * Copyright (c) 2022 Shinya Ishikawa + * + * This file is part of the Moddable SDK Tools. + * + * The Moddable SDK Tools is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Moddable SDK Tools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Moddable SDK Tools. If not, see . + * + */ +import type { Buffer } from "embedded:io/_common"; +import type UDP from "embedded:io/socket/udp"; declare module "embedded:io/socket/tcp" { - import type { Buffer } from "embedded:io/_common"; - export type TCPSocketOptions = ((({ - address: string; - } | { - host: string; + export type TCPOptions = ((({ + address: string; + } | { + host: string; }) & { - port: number; + port: number; }) | { - from: TCP; + from: TCP; }) & { - nodelay?: boolean; - onReadable?: (this: TCP, bytes: number) => void; - onWritable?: (this: TCP, bytes: number) => void; - onError?: (this: TCP) => void; - format?: "number" | "buffer"; - target?: any; - }; - - export default class TCP { - constructor(options: TCPSocketOptions) - readonly remoteAddress: string | undefined; - readonly remotePort: number | undefined; - read(byteLength?: number): number | ArrayBuffer; - read(buffer: Buffer): void; - write(value: number | Buffer): void; - close(): void; - get format(): "number" | "buffer" - set format(value: "number" | "buffer") - } + nodelay?: boolean; + onReadable?: (this: TCP, bytes: number) => void; + onWritable?: (this: TCP, bytes: number) => void; + onError?: (this: TCP) => void; + format?: "number" | "buffer"; + // target?: any; // this does not appear in the implementation? +}; + + export type TCPDevice = TCPOptions & { io: typeof UDP }; + + export default class TCP { + constructor(options: TCPOptions); + readonly remoteAddress: string | undefined; + readonly remotePort: number | undefined; + read(byteLength?: number): number | ArrayBuffer; + read(buffer: Buffer): void; + write(value: number | Buffer): void; + close(): void; + get format(): "number" | "buffer"; + set format(value: "number" | "buffer"); + } } diff --git a/typings/embedded_io/socket/tcp/tls.d.ts b/typings/embedded_io/socket/tcp/tls.d.ts index 0c8d53967b..a217597252 100644 --- a/typings/embedded_io/socket/tcp/tls.d.ts +++ b/typings/embedded_io/socket/tcp/tls.d.ts @@ -1,16 +1,19 @@ declare module "embedded:io/socket/tcp/tls" { - import { TCPSocketOptions as TCPOptions } from "embedded:io/socket/tcp" - export type TLSSocketOptions = TCPOptions & { - host: string - secure: Record // should be called "tls" according to std? - } - export default class TLSSocket { - constructor(options: TLSSocketOptions) - close(): undefined - read(count: number|ArrayBufferLike) : undefined|ArrayBufferLike - write(buffer: ArrayBufferLike) : number - set format(format: string) - get format() : string - } -} + import { TCPOptions } from "embedded:io/socket/tcp"; + import UDP from "embedded:io/socket/udp"; + + export type TLSOptions = TCPOptions & { + host: string; + secure: Record; // should be called "tls" according to std? + }; + export type TLSDevice = TCPOptions & { io: typeof UDP }; + export default class TLSSocket { + constructor(options: TLSOptions); + close(): undefined; + read(count: number | ArrayBufferLike): undefined | ArrayBufferLike; + write(buffer: ArrayBufferLike): number; + set format(format: string); + get format(): string; + } +} diff --git a/typings/embedded_io/socket/udp.d.ts b/typings/embedded_io/socket/udp.d.ts index e9f4846ab3..4a9ed337de 100644 --- a/typings/embedded_io/socket/udp.d.ts +++ b/typings/embedded_io/socket/udp.d.ts @@ -20,27 +20,36 @@ declare module "embedded:io/socket/udp" { import type { Buffer } from "embedded:io/_common"; + + interface UDPOptionsBase { + port?: number; + address?: string; + onReadable?: (this: UDP, packets: number) => void; + onError?: () => void; + format?: "buffer"; + // target?: any; // this does not appear in the implementation? + } + + interface UDPMulticastOptions { + multicast: string; + timeToLive: number; + } + + export type UDPOptions = UDPOptionsBase & ({} | UDPMulticastOptions); + + export type UDPDevice = UDPOptions & { io: typeof UDP }; + class UDP { - constructor(options: { - port?: number; - address?: string; - onReadable?: (this: UDP, packets: number) => void; - onError?: () => void; - format?: "buffer"; - target?: any; - } & ({} | { - multicast: string; - timeToLive: number; - })) + constructor(options: UDPOptions) write(buffer: Buffer, address: string, port: number): void; read(): ArrayBuffer & { address: string; port: number; }; - read(buffer: Buffer); + read(buffer: Buffer): number; get format(): "buffer" set format(value: "buffer") } - - export default UDP + + export default UDP; } diff --git a/typings/embedded_network/dns/resolver/udp.d.ts b/typings/embedded_network/dns/resolver/udp.d.ts index f554acf3dc..49e30f13c3 100644 --- a/typings/embedded_network/dns/resolver/udp.d.ts +++ b/typings/embedded_network/dns/resolver/udp.d.ts @@ -19,23 +19,27 @@ */ declare module "embedded:network/dns/resolver/udp" { + import type { UDPDevice } from 'embedded:io/socket/udp'; export interface DNSUDPOptions { http: never; servers: string[]; + socket: UDPDevice; } - interface ResolveOptions { - host: string - onResolved: ((host:string, address:any) => null) - onError: ((host:string) => null) + + export interface DNSUDPResolveOptions { + host: string; + onResolved: ((host:string, address:any) => null); + onError: ((host:string) => null); } - class Resolver { - constructor(options: DNSUDPOptions) - close(): void - resolve(options: ResolveOptions): void + export type DNSUDPDevice = DNSUDPOptions & { io: typeof Resolver }; + class Resolver { + constructor(options: DNSUDPOptions); + close(): void; + resolve(options: DNSUDPResolveOptions): void; } - export default Resolver + export default Resolver; } diff --git a/typings/embedded_network/websocket/client-device.d.ts b/typings/embedded_network/websocket/client-device.d.ts new file mode 100644 index 0000000000..a724a0969d --- /dev/null +++ b/typings/embedded_network/websocket/client-device.d.ts @@ -0,0 +1,22 @@ +import type { DNSUDPDevice } from "embedded:network/dns/resolver/udp"; +import type { TLSDevice } from "embedded:io/socket/tcp/tls"; +import type WebSocketClient from "embedded:network/websocket/client"; + +declare global { + interface WSNetwork { + ws: { + io: typeof WebSocketClient; + dns: DNSUDPDevice; + }; + wss: { + io: typeof WebSocketClient; + dns: DNSUDPDevice; + socket: TLSDevice; + }; + } + + interface Device { + network: WSNetwork; + } +} + diff --git a/typings/embedded_network/websocket/client.d.ts b/typings/embedded_network/websocket/client.d.ts index 07bf4cc18d..5f3ad57495 100644 --- a/typings/embedded_network/websocket/client.d.ts +++ b/typings/embedded_network/websocket/client.d.ts @@ -1,11 +1,12 @@ -declare module 'embedded:network/websocket/client' { - import type { DNSUDPOptions } from 'embedded:network/dns/resolver/udp'; - import type { Buffer } from 'embedded:io/_common'; - import type TCP from 'embedded:io/socket/tcp'; - import type { TCPSocketOptions } from 'embedded:io/socket/tcp'; - import type TLSSocket from 'embedded:io/socket/tcp/tls'; - import type { TLSSocketOptions } from 'embedded:io/socket/tcp/tls'; - +declare module "embedded:network/websocket/client" { + import type { DNSUDPOptions } from "embedded:network/dns/resolver/udp"; + import type { Buffer } from "embedded:io/_common"; + import type TCP from "embedded:io/socket/tcp"; + import type { TCPOptions } from "embedded:io/socket/tcp"; + import type TLSSocket from "embedded:io/socket/tcp/tls"; + import type { TLSOptions } from "embedded:io/socket/tcp/tls"; + import "embedded:network/websocket/client-device"; + interface WebSocketClientReadableOptions { more: boolean; binary: boolean; @@ -21,12 +22,12 @@ declare module 'embedded:network/websocket/client' { interface WebSocketClientOptions { attach?: TCP | TLSSocket; - socket?: TCPSocketOptions | TLSSocketOptions; + socket?: TCPOptions | TLSOptions; host?: string; port?: number; protocol?: string; headers?: Map; - dns?: DNSUDPOptions; // spec says required, but when using attach it appears to be optional? + dns?: DNSUDPOptions; onReadable?: (count: number, options?: WebSocketClientReadableOptions) => void; onWritable?: (count: number) => void; onControl?: (opcode: WebSocketClientOpcode, buffer: Uint8Array) => void; // should this be ArrayBuffer? diff --git a/typings/embedded_provider/builtin-global.d.ts b/typings/embedded_provider/builtin-global.d.ts new file mode 100644 index 0000000000..934f53bbd4 --- /dev/null +++ b/typings/embedded_provider/builtin-global.d.ts @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2022 Shinya Ishikawa +* +* This file is part of the Moddable SDK Tools. +* +* The Moddable SDK Tools is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* The Moddable SDK Tools is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with the Moddable SDK Tools. If not, see . +* +*/ + +import Digital from "embedded:io/digital"; +import DigitalBank from "embedded:io/digitalbank"; +import Analog from "embedded:io/analog"; +import PWM from "embedded:io/pwm"; +import PulseCount from "embedded:io/pulsecount"; +import I2C from "embedded:io/i2c"; +import SMBus from "embedded:io/smbus"; +import SPI from "embedded:io/spi"; +import Serial from "embedded:io/serial"; +import type { PinSpecifier } from "embedded:io/_common"; + +declare global { + interface Device { + io: { + Digital: typeof Digital; + DigitalBank: typeof DigitalBank; + Analog: typeof Analog; + PWM: typeof PWM; + PulseCount: typeof PulseCount; + I2C: typeof I2C; + SMBus: typeof SMBus; + SPI: typeof SPI; + Serial: typeof Serial; + }; + Digital: { default: ConstructorParameters[0] }; + DigitalBank: { default: ConstructorParameters[0] }; + Analog: { default: ConstructorParameters[0] }; + PWM: { default: ConstructorParameters[0] }; + PulseCount: { default: ConstructorParameters[0] }; + I2C: { default: ConstructorParameters[0] }; + SMBus: { default: ConstructorParameters[0] }; + SPI: { default: ConstructorParameters[0] }; + Serial: { default: ConstructorParameters[0] }; + pin: { [name: string]: PinSpecifier }; + } +} diff --git a/typings/embedded_provider/builtin.d.ts b/typings/embedded_provider/builtin.d.ts index 0948bd816a..9b4a69a3ab 100644 --- a/typings/embedded_provider/builtin.d.ts +++ b/typings/embedded_provider/builtin.d.ts @@ -18,52 +18,6 @@ * */ - declare module "embedded:provider/builtin" { - import Digital from "embedded:io/digital"; - import DigitalBank from "embedded:io/digitalbank"; - import Analog from "embedded:io/analog"; - import PWM from "embedded:io/pwm"; - import PulseCount from "embedded:io/pulsecount"; - import I2C from "embedded:io/i2c"; - import SMBus from "embedded:io/smbus"; - import SPI from "embedded:io/spi"; - import Serial from "embedded:io/serial"; - import type WebSocketClient from 'embedded:network/websocket/client'; - import type { WebSocketClientOptions } from 'embedded:network/websocket/client'; - import type { PinSpecifier } from "embedded:io/_common"; - const device: { - io: { - Digital: typeof Digital; - DigitalBank: typeof DigitalBank; - Analog: typeof Analog; - PWM: typeof PWM; - PulseCount: typeof PulseCount; - I2C: typeof I2C; - SMBus: typeof SMBus; - SPI: typeof SPI; - Serial: typeof Serial; - }; - Digital: { default: ConstructorParameters[0] }; - DigitalBank: { default: ConstructorParameters[0] }; - Analog: { default: ConstructorParameters[0] }; - PWM: { default: ConstructorParameters[0] }; - PulseCount: { default: ConstructorParameters[0] }; - I2C: { default: ConstructorParameters[0] }; - SMBus: { default: ConstructorParameters[0] }; - SPI: { default: ConstructorParameters[0] }; - Serial: { default: ConstructorParameters[0] }; - pin: { [name: string]: PinSpecifier }; - network: { - ws: { - io: typeof WebSocketClient; - client: WebSocketClientOptions; - } - wss: { - io: typeof WebSocketClient; - client: WebSocketClientOptions; - } - }; - }; export default device; -} +} \ No newline at end of file diff --git a/typings/global.d.ts b/typings/global.d.ts index be64bba413..97bfb438b3 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -1,9 +1,8 @@ import System_ from "embedded:io/system" -import Device from "embedded:provider/builtin" +import "embedded:provider/builtin-global" -export {} declare global { // NOTE: `System` is non-standard and temporary to support the IO examples. Breaking changes are possible. var System: typeof System_; - var device: typeof Device; + var device: Device; } From afeb5663c9dd9191977998120aea36b684eb6ccb Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sat, 19 Oct 2024 19:11:53 -0400 Subject: [PATCH 07/23] Removed unused import --- examples/io/tcp/websocketsclient/config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/io/tcp/websocketsclient/config.js b/examples/io/tcp/websocketsclient/config.js index c8ea8951ac..99096592ca 100644 --- a/examples/io/tcp/websocketsclient/config.js +++ b/examples/io/tcp/websocketsclient/config.js @@ -1,6 +1,5 @@ import "system" // system initializes globalThis.device. this ensures it runs before this module. -import TCP from "embedded:io/socket/tcp"; import UDP from "embedded:io/socket/udp"; import Resolver from "embedded:network/dns/resolver/udp"; import TLSSocket from "embedded:io/socket/tcp/tls"; From 04a118f5a93917a514e619d108ced0df5cde8dcc Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sat, 19 Oct 2024 19:12:17 -0400 Subject: [PATCH 08/23] Fixed module imports to be within declare --- typings/embedded_io/socket/tcp.d.ts | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/typings/embedded_io/socket/tcp.d.ts b/typings/embedded_io/socket/tcp.d.ts index 6f003127ea..d1c5d780d2 100644 --- a/typings/embedded_io/socket/tcp.d.ts +++ b/typings/embedded_io/socket/tcp.d.ts @@ -17,26 +17,26 @@ * along with the Moddable SDK Tools. If not, see . * */ -import type { Buffer } from "embedded:io/_common"; -import type UDP from "embedded:io/socket/udp"; - declare module "embedded:io/socket/tcp" { + import type { Buffer } from "embedded:io/_common"; + import type UDP from "embedded:io/socket/udp"; + export type TCPOptions = ((({ - address: string; + address: string; } | { - host: string; - }) & { - port: number; - }) | { - from: TCP; - }) & { - nodelay?: boolean; - onReadable?: (this: TCP, bytes: number) => void; - onWritable?: (this: TCP, bytes: number) => void; - onError?: (this: TCP) => void; - format?: "number" | "buffer"; - // target?: any; // this does not appear in the implementation? -}; + host: string; + }) & { + port: number; + }) | { + from: TCP; + }) & { + nodelay?: boolean; + onReadable?: (this: TCP, bytes: number) => void; + onWritable?: (this: TCP, bytes: number) => void; + onError?: (this: TCP) => void; + format?: "number" | "buffer"; + // target?: any; // this does not appear in the implementation? + }; export type TCPDevice = TCPOptions & { io: typeof UDP }; From b6e275ebfa37cf39a376dc82634ed3123da007dc Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sun, 20 Oct 2024 10:00:27 -0400 Subject: [PATCH 09/23] More refinements/improvements to tcp/udp/dns/websocket types --- typings/embedded_io/socket/tcp.d.ts | 30 +++++++------- typings/embedded_io/socket/tcp/tls.d.ts | 15 ++++++- typings/embedded_io/socket/udp.d.ts | 1 - .../embedded_network/dns/resolver/udp.d.ts | 2 +- .../websocket/client-device.d.ts | 2 + .../embedded_network/websocket/client.d.ts | 40 +++++++++++-------- 6 files changed, 54 insertions(+), 36 deletions(-) diff --git a/typings/embedded_io/socket/tcp.d.ts b/typings/embedded_io/socket/tcp.d.ts index d1c5d780d2..58cb673522 100644 --- a/typings/embedded_io/socket/tcp.d.ts +++ b/typings/embedded_io/socket/tcp.d.ts @@ -21,22 +21,20 @@ declare module "embedded:io/socket/tcp" { import type { Buffer } from "embedded:io/_common"; import type UDP from "embedded:io/socket/udp"; - export type TCPOptions = ((({ - address: string; - } | { - host: string; - }) & { - port: number; - }) | { - from: TCP; - }) & { - nodelay?: boolean; - onReadable?: (this: TCP, bytes: number) => void; - onWritable?: (this: TCP, bytes: number) => void; - onError?: (this: TCP) => void; - format?: "number" | "buffer"; - // target?: any; // this does not appear in the implementation? - }; + export type TCPOptions = (( + { + address: string; + port: number; + } | { + from: TCP; + }) & { + nodelay?: boolean; + onReadable?: (this: TCP, bytes: number) => void; + onWritable?: (this: TCP, bytes: number) => void; + onError?: (this: TCP) => void; + format?: "number" | "buffer"; + } + ); export type TCPDevice = TCPOptions & { io: typeof UDP }; diff --git a/typings/embedded_io/socket/tcp/tls.d.ts b/typings/embedded_io/socket/tcp/tls.d.ts index a217597252..e90b65bfdb 100644 --- a/typings/embedded_io/socket/tcp/tls.d.ts +++ b/typings/embedded_io/socket/tcp/tls.d.ts @@ -2,9 +2,22 @@ declare module "embedded:io/socket/tcp/tls" { import { TCPOptions } from "embedded:io/socket/tcp"; import UDP from "embedded:io/socket/udp"; + export type SSLSessionOptions = { + protocolVersion?: number; + serverName?: string; + applicationLayerProtocolNegotiation?: string; + trace?: number; + cache?: boolean; + tls_server_name?: string; + client_auth?: { + cipherSuites: string[]; + subjectDN: string; + }; + }; + export type TLSOptions = TCPOptions & { host: string; - secure: Record; // should be called "tls" according to std? + secure: SSLSessionOptions; }; export type TLSDevice = TCPOptions & { io: typeof UDP }; diff --git a/typings/embedded_io/socket/udp.d.ts b/typings/embedded_io/socket/udp.d.ts index 4a9ed337de..ba6a539c83 100644 --- a/typings/embedded_io/socket/udp.d.ts +++ b/typings/embedded_io/socket/udp.d.ts @@ -27,7 +27,6 @@ declare module "embedded:io/socket/udp" { onReadable?: (this: UDP, packets: number) => void; onError?: () => void; format?: "buffer"; - // target?: any; // this does not appear in the implementation? } interface UDPMulticastOptions { diff --git a/typings/embedded_network/dns/resolver/udp.d.ts b/typings/embedded_network/dns/resolver/udp.d.ts index 49e30f13c3..0c0d269356 100644 --- a/typings/embedded_network/dns/resolver/udp.d.ts +++ b/typings/embedded_network/dns/resolver/udp.d.ts @@ -22,7 +22,7 @@ declare module "embedded:network/dns/resolver/udp" { import type { UDPDevice } from 'embedded:io/socket/udp'; export interface DNSUDPOptions { - http: never; + http?: never; servers: string[]; socket: UDPDevice; } diff --git a/typings/embedded_network/websocket/client-device.d.ts b/typings/embedded_network/websocket/client-device.d.ts index a724a0969d..23fa3df109 100644 --- a/typings/embedded_network/websocket/client-device.d.ts +++ b/typings/embedded_network/websocket/client-device.d.ts @@ -1,4 +1,5 @@ import type { DNSUDPDevice } from "embedded:network/dns/resolver/udp"; +import type { TCPDevice } from 'embedded:io/socket/tcp'; import type { TLSDevice } from "embedded:io/socket/tcp/tls"; import type WebSocketClient from "embedded:network/websocket/client"; @@ -7,6 +8,7 @@ declare global { ws: { io: typeof WebSocketClient; dns: DNSUDPDevice; + socket: TCPDevice }; wss: { io: typeof WebSocketClient; diff --git a/typings/embedded_network/websocket/client.d.ts b/typings/embedded_network/websocket/client.d.ts index 5f3ad57495..e0cc0262fb 100644 --- a/typings/embedded_network/websocket/client.d.ts +++ b/typings/embedded_network/websocket/client.d.ts @@ -1,10 +1,10 @@ declare module "embedded:network/websocket/client" { - import type { DNSUDPOptions } from "embedded:network/dns/resolver/udp"; + import type { DNSUDPDevice } from "embedded:network/dns/resolver/udp"; import type { Buffer } from "embedded:io/_common"; import type TCP from "embedded:io/socket/tcp"; - import type { TCPOptions } from "embedded:io/socket/tcp"; + import type { TCPDevice } from "embedded:io/socket/tcp"; import type TLSSocket from "embedded:io/socket/tcp/tls"; - import type { TLSOptions } from "embedded:io/socket/tcp/tls"; + import type { TLSDevice } from "embedded:io/socket/tcp/tls"; import "embedded:network/websocket/client-device"; interface WebSocketClientReadableOptions { @@ -20,20 +20,26 @@ declare module "embedded:network/websocket/client" { type WebSocketClientOpcode = 1 | 2 | 8 | 9 | 10; - interface WebSocketClientOptions { - attach?: TCP | TLSSocket; - socket?: TCPOptions | TLSOptions; - host?: string; - port?: number; - protocol?: string; - headers?: Map; - dns?: DNSUDPOptions; - onReadable?: (count: number, options?: WebSocketClientReadableOptions) => void; - onWritable?: (count: number) => void; - onControl?: (opcode: WebSocketClientOpcode, buffer: Uint8Array) => void; // should this be ArrayBuffer? - onClose?: () => void; - onError?: () => void; - } + type WebSocketClientOptions = (( + { + attach?: TCP | TLSSocket; + } | { + host?: string; + port?: number; + socket: TCPDevice | TLSDevice; + }) & { + protocol?: string; + headers?: Map; + dns?: DNSUDPDevice; + onReadable?: (count: number, options?: WebSocketClientReadableOptions) => void; + onWritable?: (count: number) => void; + onControl?: (opcode: WebSocketClientOpcode, buffer: Uint8Array) => void; // should this be ArrayBuffer? + onClose?: () => void; + onError?: () => void; + } + ); + + export type WebSocketClientDevice = WebSocketClientOptions & { io: typeof WebSocketClient }; export default class WebSocketClient { constructor(options: WebSocketClientOptions); From 365854b126afefdba5326c9d907770f802ec5353 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sun, 20 Oct 2024 19:32:31 -0400 Subject: [PATCH 10/23] More io types, expanded webpage w/status and headers, fixed up 'this' on callbacks --- .../io/listener/httpserver/options/webpage.js | 3 +- examples/manifest_typings.json | 3 ++ typings/embedded_io/socket/listener.d.ts | 22 ++++++---- typings/embedded_io/socket/tcp.d.ts | 3 +- typings/embedded_network/http/client.d.ts | 22 ++++++---- .../embedded_network/http/server-device.d.ts | 19 +++++++++ typings/embedded_network/http/server.d.ts | 41 +++++++++++++++++++ .../http/server/options/webpage.d.ts | 13 ++++++ .../http/server/options/websocket.d.ts | 8 ++++ .../websocket/client-device.d.ts | 7 ++-- .../embedded_network/websocket/client.d.ts | 12 +++--- 11 files changed, 126 insertions(+), 27 deletions(-) create mode 100644 typings/embedded_network/http/server-device.d.ts create mode 100644 typings/embedded_network/http/server.d.ts create mode 100644 typings/embedded_network/http/server/options/webpage.d.ts create mode 100644 typings/embedded_network/http/server/options/websocket.d.ts diff --git a/examples/io/listener/httpserver/options/webpage.js b/examples/io/listener/httpserver/options/webpage.js index b0582339bc..f5140d3108 100644 --- a/examples/io/listener/httpserver/options/webpage.js +++ b/examples/io/listener/httpserver/options/webpage.js @@ -21,7 +21,8 @@ export default { onResponse(response) { response.headers.set("content-length", this.route.msg.byteLength); - response.headers.set("content-type", "text/html"); + response.headers.set("content-type", this.route.contentType ?? "text/html"); + response.status = this.route.status ?? 200; this.respond(response); }, onWritable(count) { diff --git a/examples/manifest_typings.json b/examples/manifest_typings.json index 276139e4b4..a02eb205d4 100644 --- a/examples/manifest_typings.json +++ b/examples/manifest_typings.json @@ -39,6 +39,9 @@ "embedded:network/http/*": [ "$(TYPINGS)/embedded_network/http/*" ], + "embedded:network/http/server/options/*": [ + "$(TYPINGS)/embedded_network/http/server/options/*" + ], "embedded:network/mqtt/*": [ "$(TYPINGS)/embedded_network/mqtt/*" ], diff --git a/typings/embedded_io/socket/listener.d.ts b/typings/embedded_io/socket/listener.d.ts index 1842a953dd..1334f304c9 100644 --- a/typings/embedded_io/socket/listener.d.ts +++ b/typings/embedded_io/socket/listener.d.ts @@ -19,19 +19,25 @@ */ declare module "embedded:io/socket/listener" { - import TCP from "embedded:io/socket/tcp" + import type TCP from "embedded:io/socket/tcp"; + + export interface ListenerOptions { + port?: number; + address?: string; + onReadable?: (this: Listener, bytes: number) => void; + format?: "socket/tcp"; + } + + export type ListenerDevice = ListenerOptions & { io: typeof Listener }; + class Listener { - constructor(options: { - port?: number; - address?: string; - onReadable?: (this: Listener, requests: number) => void; - format?: "socket/tcp"; - target?: any; - }) + constructor(options: ListenerOptions) read(): TCP | undefined get format(): "socket/tcp" set format(value: "socket/tcp") + readonly port: number; } + export default Listener; } diff --git a/typings/embedded_io/socket/tcp.d.ts b/typings/embedded_io/socket/tcp.d.ts index 58cb673522..0dc30263ae 100644 --- a/typings/embedded_io/socket/tcp.d.ts +++ b/typings/embedded_io/socket/tcp.d.ts @@ -42,7 +42,8 @@ declare module "embedded:io/socket/tcp" { constructor(options: TCPOptions); readonly remoteAddress: string | undefined; readonly remotePort: number | undefined; - read(byteLength?: number): number | ArrayBuffer; + read(): number; + read(byteLength: number): ArrayBuffer; read(buffer: Buffer): void; write(value: number | Buffer): void; close(): void; diff --git a/typings/embedded_network/http/client.d.ts b/typings/embedded_network/http/client.d.ts index b928e606ad..21ab3396d9 100644 --- a/typings/embedded_network/http/client.d.ts +++ b/typings/embedded_network/http/client.d.ts @@ -20,12 +20,15 @@ declare module "embedded:network/http/client" { import type { Buffer } from "embedded:io/_common" + import type { TCPDevice } from "embedded:io/socket/tcp"; + import type { TLSDevice } from "embedded:io/socket/tls"; + import type { DNSUDPDevice } from "embedded:io/socket/dns"; - export interface ClientOptions { - socket: any - port?:number - host: string - dns: any + export interface HTTPClientOptions { + socket: TCPDevice | TLSDevice; + port?: number; + host: string; + dns: DNSUDPDevice; onError?: (err:any)=>void } @@ -39,14 +42,17 @@ declare module "embedded:network/http/client" { onDone?: (this: HTTPRequest, error: Error|null) => void // note: error is empty Error object } + export type HTTPClientDevice = HTTPClientOptions & { io: typeof HTTPClient }; + export interface HTTPRequest { - read(byteLength?: number): ArrayBuffer|undefined; - read(buffer: Buffer): void; + read(): number; + read(byteLength: number): ArrayBuffer; + read(buffer: Buffer): void; write(value: Buffer|undefined): void; } export default class HTTPClient { - constructor(options: ClientOptions) + constructor(options: HTTPClientOptions) request(options: RequestOptions): HTTPRequest close(): void } diff --git a/typings/embedded_network/http/server-device.d.ts b/typings/embedded_network/http/server-device.d.ts new file mode 100644 index 0000000000..a09fb17f78 --- /dev/null +++ b/typings/embedded_network/http/server-device.d.ts @@ -0,0 +1,19 @@ +import type { DNSUDPDevice } from "embedded:network/dns/resolver/udp"; +import type { TCPDevice } from 'embedded:io/socket/tcp'; +import HTTPServer from "embedded:network/http/server"; + + +declare global { + interface NetworkExtensions { + http: { + io: typeof HTTPServer; + dns: DNSUDPDevice; + socket: TCPDevice + }; + } + + interface Device { + network: NetworkExtensions; + } +} + diff --git a/typings/embedded_network/http/server.d.ts b/typings/embedded_network/http/server.d.ts new file mode 100644 index 0000000000..3e6d09b4ef --- /dev/null +++ b/typings/embedded_network/http/server.d.ts @@ -0,0 +1,41 @@ +declare module "embedded:network/http/server" { + import type Listener from "embedded:io/socket/listener"; + import type TCP from "embedded:io/socket/tcp"; + import "embedded:network/http/server-device"; + + export interface HTTPServerOptions { + io: typeof Listener; + port?: number; + onConnect?: (this: HTTPServer, connection: HTTPServerConnection) => void; + } + + export interface HTTPServerRoute { + onRequest?: (this: HTTPServerConnection, request: { method: string, path: string, headers: Map}) => void; + onReadable?: (this: HTTPServerConnection, count: number) => void; + onResponse?: (this: HTTPServerConnection, response: HTTPServerResponseOptions) => void; + onWritable?: (this: HTTPServerConnection, count: number) => void; + onDone?: (this: HTTPServerConnection, ) => void; + onError?: (this: HTTPServerConnection, error?: string) => void; + } + + export interface HTTPServerResponseOptions { + status: number; + headers: Map; + } + + export interface HTTPServerConnection { + close(): void; + detach(): TCP; + accept(options: HTTPServerRoute): void; + respond(options: HTTPServerResponseOptions): void; + read(count: number): ArrayBuffer; + write(payload?: ArrayBuffer): number; + route: HTTPServerRoute; + } + + export default class HTTPServer { + constructor(options: HTTPServerOptions); + close(): void + } + } + \ No newline at end of file diff --git a/typings/embedded_network/http/server/options/webpage.d.ts b/typings/embedded_network/http/server/options/webpage.d.ts new file mode 100644 index 0000000000..3b44f66d44 --- /dev/null +++ b/typings/embedded_network/http/server/options/webpage.d.ts @@ -0,0 +1,13 @@ +declare module "embedded:network/http/server/options/webpage" { + import type { HTTPServerRoute } from "embedded:network/http/server"; + import type { Buffer } from "embedded:io/_common"; + + export interface HTTPServerRouteWebPage extends HTTPServerRoute { + msg: Buffer | string; + contentType?: string; + headers?: Map; + status?: number; + } + const route: HTTPServerRouteWebPage; + export default route; +} \ No newline at end of file diff --git a/typings/embedded_network/http/server/options/websocket.d.ts b/typings/embedded_network/http/server/options/websocket.d.ts new file mode 100644 index 0000000000..4ab9a49191 --- /dev/null +++ b/typings/embedded_network/http/server/options/websocket.d.ts @@ -0,0 +1,8 @@ +declare module "embedded:network/http/server/options/websocket" { + import type { HTTPServerRoute } from "embedded:network/http/server"; + + export interface HTTPServerRouteWebSocket extends HTTPServerRoute {} + + const route: HTTPServerRouteWebSocket; + export default route; +} diff --git a/typings/embedded_network/websocket/client-device.d.ts b/typings/embedded_network/websocket/client-device.d.ts index 23fa3df109..cbc68e2612 100644 --- a/typings/embedded_network/websocket/client-device.d.ts +++ b/typings/embedded_network/websocket/client-device.d.ts @@ -4,7 +4,7 @@ import type { TLSDevice } from "embedded:io/socket/tcp/tls"; import type WebSocketClient from "embedded:network/websocket/client"; declare global { - interface WSNetwork { + interface NetworkExtensions { ws: { io: typeof WebSocketClient; dns: DNSUDPDevice; @@ -17,8 +17,9 @@ declare global { }; } - interface Device { - network: WSNetwork; + interface Device { + network: NetworkExtensions; } + } diff --git a/typings/embedded_network/websocket/client.d.ts b/typings/embedded_network/websocket/client.d.ts index e0cc0262fb..207a6daa72 100644 --- a/typings/embedded_network/websocket/client.d.ts +++ b/typings/embedded_network/websocket/client.d.ts @@ -29,13 +29,13 @@ declare module "embedded:network/websocket/client" { socket: TCPDevice | TLSDevice; }) & { protocol?: string; - headers?: Map; + headers?: Map; dns?: DNSUDPDevice; - onReadable?: (count: number, options?: WebSocketClientReadableOptions) => void; - onWritable?: (count: number) => void; - onControl?: (opcode: WebSocketClientOpcode, buffer: Uint8Array) => void; // should this be ArrayBuffer? - onClose?: () => void; - onError?: () => void; + onReadable?: (this: WebSocketClient, count: number, options?: WebSocketClientReadableOptions) => void; + onWritable?: (this: WebSocketClient, count: number) => void; + onControl?: (this: WebSocketClient, opcode: WebSocketClientOpcode, buffer: Uint8Array) => void; // should this be ArrayBuffer? + onClose?: (this: WebSocketClient, ) => void; + onError?: (this: WebSocketClient, ) => void; } ); From 72b162a41eb3b3b3ac6729595703101bfdf16ba3 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Mon, 21 Oct 2024 18:27:43 -0400 Subject: [PATCH 11/23] Add status codes to http/1.1 response --- examples/io/listener/httpserver/httpserver.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/examples/io/listener/httpserver/httpserver.js b/examples/io/listener/httpserver/httpserver.js index a4bae11baa..1577bec82a 100644 --- a/examples/io/listener/httpserver/httpserver.js +++ b/examples/io/listener/httpserver/httpserver.js @@ -20,6 +20,20 @@ import Timer from "timer"; +const statusReasons = Object.freeze({ + 200: "OK", + 201: "Created", + 204: "No Content", + 301: "Moved Permanently", + 302: "Found", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 500: "Internal Server Error", + 503: "Service Unavailable", +}); + class Connection { #server; #socket; @@ -288,7 +302,7 @@ class Connection { switch (this.#state) { case "sendResponse": - this.#pendingWrite = `HTTP/1.1 ${this.#options.status} FILL_THIS_IN\r\n`; + this.#pendingWrite = `HTTP/1.1 ${this.#options.status} ${statusReasons[this.#options.status] ?? ""}\r\n`; this.#pendingWrite = ArrayBuffer.fromString(this.#pendingWrite); this.#writePosition = 0; From 2d935cbc477c85a146c2b2807a78c29ececfc7fa Mon Sep 17 00:00:00 2001 From: cmidgley Date: Mon, 21 Oct 2024 18:28:08 -0400 Subject: [PATCH 12/23] Fix bug with attach socket --- examples/io/tcp/websocket/WebSocket.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/io/tcp/websocket/WebSocket.js b/examples/io/tcp/websocket/WebSocket.js index 8e1d016967..799f662bb0 100644 --- a/examples/io/tcp/websocket/WebSocket.js +++ b/examples/io/tcp/websocket/WebSocket.js @@ -48,7 +48,7 @@ class WebSocket { keepalive = options.keepalive; headers = options.headers; } - if (href) { + else if (href) { let url = new URL(href); let scheme = url.protocol; let port, config; From e002eabc1ca14730d6509c3ea1f7ce5bdf9282be Mon Sep 17 00:00:00 2001 From: cmidgley Date: Mon, 21 Oct 2024 18:28:37 -0400 Subject: [PATCH 13/23] Further type improvements for websocketclient --- typings/embedded_network/websocket/client.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typings/embedded_network/websocket/client.d.ts b/typings/embedded_network/websocket/client.d.ts index 207a6daa72..808299f829 100644 --- a/typings/embedded_network/websocket/client.d.ts +++ b/typings/embedded_network/websocket/client.d.ts @@ -31,11 +31,11 @@ declare module "embedded:network/websocket/client" { protocol?: string; headers?: Map; dns?: DNSUDPDevice; - onReadable?: (this: WebSocketClient, count: number, options?: WebSocketClientReadableOptions) => void; + onReadable?: (this: WebSocketClient, count: number, options: WebSocketClientReadableOptions) => void; onWritable?: (this: WebSocketClient, count: number) => void; onControl?: (this: WebSocketClient, opcode: WebSocketClientOpcode, buffer: Uint8Array) => void; // should this be ArrayBuffer? - onClose?: (this: WebSocketClient, ) => void; - onError?: (this: WebSocketClient, ) => void; + onClose?: (this: WebSocketClient) => void; + onError?: (this: WebSocketClient, error?: string) => void; } ); From a0c86dfcf50382fae64cb8491c7bc63b5a42034f Mon Sep 17 00:00:00 2001 From: cmidgley Date: Mon, 21 Oct 2024 18:30:00 -0400 Subject: [PATCH 14/23] Add onError error messages, don't use masks on server (attached sockets), fix bug with masks on fragmented reads, and add mask decode to control messages --- .../io/tcp/websocketclient/websocketclient.js | 62 ++++++++++++------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/examples/io/tcp/websocketclient/websocketclient.js b/examples/io/tcp/websocketclient/websocketclient.js index 4a95324741..cd17c546d1 100644 --- a/examples/io/tcp/websocketclient/websocketclient.js +++ b/examples/io/tcp/websocketclient/websocketclient.js @@ -44,7 +44,7 @@ class WebSocketClient { from: attach, onReadable: count => this.#onReadable(count), onWritable: count => this.#onWritable(count), - onError: () => this.#onError() + onError: () => this.#onError('ws: unknown socket error') }); this.#state = "connected"; return; @@ -71,15 +71,15 @@ class WebSocketClient { port: this.#options.port, onReadable: count => this.#onReadable(count), onWritable: count => this.#onWritable(count), - onError: () => this.#onError() + onError: () => this.#onError('ws: unknown socket error') }); } catch { - this.#onError?.(); + this.#onError?.('ws: unknown socket connect error'); } }, onError: () => { - this.#onError?.(); + this.#onError?.('dns: unknown resolution error'); }, }); } @@ -120,17 +120,28 @@ class WebSocketClient { } data = data.slice(0); - const mask = Uint8Array.of(Math.random() * 256, Math.random() * 256, Math.random() * 256, Math.random() * 256); - Logical.xor(data, mask.buffer); const format = this.#socket.format; this.#socket.format = "buffer"; - if (byteLength < 126) { - this.#socket.write(Uint8Array.of(type, byteLength | 0x80, mask[0], mask[1], mask[2], mask[3])); - this.#writable -= (6 + byteLength); - } - else { - this.#socket.write(Uint8Array.of(type, 126 | 0x80, byteLength >> 8, byteLength, mask[0], mask[1], mask[2], mask[3])); - this.#writable -= (8 + byteLength); + if (this.#options.attach) { + const mask = Uint8Array.of(Math.random() * 256, Math.random() * 256, Math.random() * 256, Math.random() * 256); + Logical.xor(data, mask.buffer); + if (byteLength < 126) { + this.#socket.write(Uint8Array.of(type, byteLength | 0x80, mask[0], mask[1], mask[2], mask[3])); + this.#writable -= (6 + byteLength); + } + else { + this.#socket.write(Uint8Array.of(type, 126 | 0x80, byteLength >> 8, byteLength, mask[0], mask[1], mask[2], mask[3])); + this.#writable -= (8 + byteLength); + } + } else { + if (byteLength < 126) { + this.#socket.write(Uint8Array.of(type, byteLength)); + this.#writable -= (2 + byteLength); + } + else { + this.#socket.write(Uint8Array.of(type, 126, byteLength >> 8, byteLength)); + this.#writable -= (4 + byteLength); + } } this.#socket.write(data); this.#socket.format = format; @@ -161,7 +172,7 @@ class WebSocketClient { if (this.#options.mask) { const mask = this.#options.mask; Logical.xor(data, mask.buffer); - if (this.#data) { + if (this.#options.length) { switch (count & 3) { case 1: this.#options.mask = Uint8Array.of(mask[1], mask[2], mask[3], mask[0]); @@ -203,16 +214,16 @@ class WebSocketClient { if ("receiveStatus" === this.#state) { let status = this.#line.split(" "); if (status.length < 3) - return void this.#onError(); + return void this.#onError('ws: http upgrade error (http status len < 3)'); status = parseInt(status[1]); if (101 !== status) - return void this.#onError(); + return void this.#onError(`ws: http upgrade error (expected status 101, got ${status})`); this.#state = "receiveHeader"; } else if ("\r\n" === this.#line) { // done if (7 !== this.#options.flags) - return void this.#onError(); + return void this.#onError(`ws: http upgrade error (insufficient header received)`); this.#state = "connected"; delete this.#options.flags; this.#socket.format = "buffer"; @@ -257,17 +268,17 @@ class WebSocketClient { count--; if (tag & 0x70) - return void this.#onError(); + return void this.#onError('ws: unsupported reserved bits'); tag &= 0x0F; - if (1 === tag & 0x0F) + if (1 === tag) options.binary = false; else if (2 === tag) options.binary = true; else if (8 & tag) options.control = true; else if (tag) - return void this.#onError(); + return void this.#onError('ws: unknown opcode (${tag})'); continue; } if (undefined === options.length) { @@ -290,7 +301,7 @@ class WebSocketClient { continue; } if (options.mask && options.mask.length < 4) { - //@@ it is an error for client to receieve a mask. this code applies to future server. client should fail here. + //@@ it is an error for client to receieve a mask. client should fail here. options.mask.push(this.#socket.read()); count--; if (4 !== options.mask.length) @@ -317,6 +328,9 @@ class WebSocketClient { return; const opcode = options.tag & 0x0F; + if (options.mask) { + Logical.xor(control, options.mask.buffer); + } try { this.#options.onControl?.call(this, opcode, control.buffer); } @@ -354,7 +368,7 @@ class WebSocketClient { else if (10 === opcode) // pong ; else - return void this.#onError(); + return void this.#onError(`ws: unknown control opcode ${opcode}`); delete options.tag; @@ -464,12 +478,12 @@ class WebSocketClient { break; } } - #onError() { + #onError(error) { this.close(); if (this.#options.close) this.#options.onClose?.call(this); else - this.#options.onError?.call(this); + this.#options.onError?.call(this, error); } static text = 1; From f88cff59935d266b40997ef901bda4f69f681dca Mon Sep 17 00:00:00 2001 From: cmidgley Date: Tue, 22 Oct 2024 08:53:44 -0400 Subject: [PATCH 15/23] Fix bug with reversed client/server on mask --- .../io/tcp/websocketclient/websocketclient.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/io/tcp/websocketclient/websocketclient.js b/examples/io/tcp/websocketclient/websocketclient.js index cd17c546d1..0f2da43cf7 100644 --- a/examples/io/tcp/websocketclient/websocketclient.js +++ b/examples/io/tcp/websocketclient/websocketclient.js @@ -123,6 +123,15 @@ class WebSocketClient { const format = this.#socket.format; this.#socket.format = "buffer"; if (this.#options.attach) { + if (byteLength < 126) { + this.#socket.write(Uint8Array.of(type, byteLength)); + this.#writable -= (2 + byteLength); + } + else { + this.#socket.write(Uint8Array.of(type, 126, byteLength >> 8, byteLength)); + this.#writable -= (4 + byteLength); + } + } else { const mask = Uint8Array.of(Math.random() * 256, Math.random() * 256, Math.random() * 256, Math.random() * 256); Logical.xor(data, mask.buffer); if (byteLength < 126) { @@ -133,15 +142,6 @@ class WebSocketClient { this.#socket.write(Uint8Array.of(type, 126 | 0x80, byteLength >> 8, byteLength, mask[0], mask[1], mask[2], mask[3])); this.#writable -= (8 + byteLength); } - } else { - if (byteLength < 126) { - this.#socket.write(Uint8Array.of(type, byteLength)); - this.#writable -= (2 + byteLength); - } - else { - this.#socket.write(Uint8Array.of(type, 126, byteLength >> 8, byteLength)); - this.#writable -= (4 + byteLength); - } } this.#socket.write(data); this.#socket.format = format; From b318fce3194957c114505a74a8a8cdcecb93fb47 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Wed, 23 Oct 2024 10:25:03 -0400 Subject: [PATCH 16/23] Switch builtin-global to builtin-device to be consistent with other types --- .../{builtin-global.d.ts => builtin-device.d.ts} | 0 typings/global.d.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename typings/embedded_provider/{builtin-global.d.ts => builtin-device.d.ts} (100%) diff --git a/typings/embedded_provider/builtin-global.d.ts b/typings/embedded_provider/builtin-device.d.ts similarity index 100% rename from typings/embedded_provider/builtin-global.d.ts rename to typings/embedded_provider/builtin-device.d.ts diff --git a/typings/global.d.ts b/typings/global.d.ts index 97bfb438b3..caa579d73e 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -1,5 +1,5 @@ import System_ from "embedded:io/system" -import "embedded:provider/builtin-global" +import "embedded:provider/builtin-device" declare global { // NOTE: `System` is non-standard and temporary to support the IO examples. Breaking changes are possible. From 629663f8eecfa60c88209beccee61436bf2d82ed Mon Sep 17 00:00:00 2001 From: cmidgley Date: Wed, 23 Oct 2024 11:34:20 -0400 Subject: [PATCH 17/23] Remove unnecessary import --- typings/global.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/typings/global.d.ts b/typings/global.d.ts index caa579d73e..e75d7f8841 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -1,5 +1,4 @@ import System_ from "embedded:io/system" -import "embedded:provider/builtin-device" declare global { // NOTE: `System` is non-standard and temporary to support the IO examples. Breaking changes are possible. From 47168b1c752f64726e97ac8c6504a7609b589c19 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Thu, 24 Oct 2024 07:01:44 -0400 Subject: [PATCH 18/23] Revert prior and apply new fix for attached sockets --- examples/io/tcp/websocket/WebSocket.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/io/tcp/websocket/WebSocket.js b/examples/io/tcp/websocket/WebSocket.js index 799f662bb0..f583593ba8 100644 --- a/examples/io/tcp/websocket/WebSocket.js +++ b/examples/io/tcp/websocket/WebSocket.js @@ -48,7 +48,7 @@ class WebSocket { keepalive = options.keepalive; headers = options.headers; } - else if (href) { + if (href) { let url = new URL(href); let scheme = url.protocol; let port, config; @@ -72,7 +72,7 @@ class WebSocket { this.#protocol = protocol; options = { ...config, host, port, path, protocol, headers } } - else + else if (!options.attach) throw new URIError("no URL"); this.#client = new device.network.ws.io({ ...options, From 876f4e066c15bd61de4287948aecef80fb666b4c Mon Sep 17 00:00:00 2001 From: cmidgley Date: Thu, 24 Oct 2024 07:02:15 -0400 Subject: [PATCH 19/23] Fix type of buffer on onControl --- typings/embedded_network/websocket/client.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/embedded_network/websocket/client.d.ts b/typings/embedded_network/websocket/client.d.ts index 808299f829..fe6cdf3f4f 100644 --- a/typings/embedded_network/websocket/client.d.ts +++ b/typings/embedded_network/websocket/client.d.ts @@ -33,7 +33,7 @@ declare module "embedded:network/websocket/client" { dns?: DNSUDPDevice; onReadable?: (this: WebSocketClient, count: number, options: WebSocketClientReadableOptions) => void; onWritable?: (this: WebSocketClient, count: number) => void; - onControl?: (this: WebSocketClient, opcode: WebSocketClientOpcode, buffer: Uint8Array) => void; // should this be ArrayBuffer? + onControl?: (this: WebSocketClient, opcode: WebSocketClientOpcode, buffer: ArrayBuffer) => void; onClose?: (this: WebSocketClient) => void; onError?: (this: WebSocketClient, error?: string) => void; } From 08e1cee2691bea8d6dfa769ac5628fc706465c74 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sun, 27 Oct 2024 09:19:20 -0400 Subject: [PATCH 20/23] Small improvements on types - tls extends tcp instead of full definition - Add 'undefined' as possible `read` result --- test262 | 1 + typings/embedded_io/socket/tcp.d.ts | 2 +- typings/embedded_io/socket/tcp/tls.d.ts | 11 ++--------- typings/embedded_network/websocket/client.d.ts | 2 +- 4 files changed, 5 insertions(+), 11 deletions(-) create mode 160000 test262 diff --git a/test262 b/test262 new file mode 160000 index 0000000000..0add42b556 --- /dev/null +++ b/test262 @@ -0,0 +1 @@ +Subproject commit 0add42b556ee5bb4ec64aa82d2e234375f39fd2f diff --git a/typings/embedded_io/socket/tcp.d.ts b/typings/embedded_io/socket/tcp.d.ts index 0dc30263ae..889565b7b9 100644 --- a/typings/embedded_io/socket/tcp.d.ts +++ b/typings/embedded_io/socket/tcp.d.ts @@ -43,7 +43,7 @@ declare module "embedded:io/socket/tcp" { readonly remoteAddress: string | undefined; readonly remotePort: number | undefined; read(): number; - read(byteLength: number): ArrayBuffer; + read(byteLength: number): ArrayBuffer | undefined; read(buffer: Buffer): void; write(value: number | Buffer): void; close(): void; diff --git a/typings/embedded_io/socket/tcp/tls.d.ts b/typings/embedded_io/socket/tcp/tls.d.ts index e90b65bfdb..b737d3323c 100644 --- a/typings/embedded_io/socket/tcp/tls.d.ts +++ b/typings/embedded_io/socket/tcp/tls.d.ts @@ -1,5 +1,5 @@ declare module "embedded:io/socket/tcp/tls" { - import { TCPOptions } from "embedded:io/socket/tcp"; + import TCP, { TCPOptions } from "embedded:io/socket/tcp"; import UDP from "embedded:io/socket/udp"; export type SSLSessionOptions = { @@ -21,12 +21,5 @@ declare module "embedded:io/socket/tcp/tls" { }; export type TLSDevice = TCPOptions & { io: typeof UDP }; - export default class TLSSocket { - constructor(options: TLSOptions); - close(): undefined; - read(count: number | ArrayBufferLike): undefined | ArrayBufferLike; - write(buffer: ArrayBufferLike): number; - set format(format: string); - get format(): string; - } + export default class TLSSocket extends TCP {} } diff --git a/typings/embedded_network/websocket/client.d.ts b/typings/embedded_network/websocket/client.d.ts index fe6cdf3f4f..22b8026138 100644 --- a/typings/embedded_network/websocket/client.d.ts +++ b/typings/embedded_network/websocket/client.d.ts @@ -44,7 +44,7 @@ declare module "embedded:network/websocket/client" { export default class WebSocketClient { constructor(options: WebSocketClientOptions); close(): void; - read(count?: number): ArrayBuffer; + read(count?: number): ArrayBuffer | undefined; write(message: Buffer, options?: WebSocketClientWriteOptions): number; static readonly text: 1; From ae61e2de58fbfeaf5d920d1241a096ee70136a35 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Fri, 2 May 2025 09:01:19 -0400 Subject: [PATCH 21/23] Import embedded:provider/builtin-device in global.d.ts to ensure Device is defined; remove udp.read(buffer); add TLSSocket.constructor with TLSOptions definition --- typings/embedded_io/socket/tcp/tls.d.ts | 4 +++- typings/embedded_io/socket/udp.d.ts | 1 - typings/global.d.ts | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/typings/embedded_io/socket/tcp/tls.d.ts b/typings/embedded_io/socket/tcp/tls.d.ts index b737d3323c..fc6ab1ab89 100644 --- a/typings/embedded_io/socket/tcp/tls.d.ts +++ b/typings/embedded_io/socket/tcp/tls.d.ts @@ -21,5 +21,7 @@ declare module "embedded:io/socket/tcp/tls" { }; export type TLSDevice = TCPOptions & { io: typeof UDP }; - export default class TLSSocket extends TCP {} + export default class TLSSocket extends TCP { + constructor(options: TLSOptions); + } } diff --git a/typings/embedded_io/socket/udp.d.ts b/typings/embedded_io/socket/udp.d.ts index ba6a539c83..60dce58cc6 100644 --- a/typings/embedded_io/socket/udp.d.ts +++ b/typings/embedded_io/socket/udp.d.ts @@ -45,7 +45,6 @@ declare module "embedded:io/socket/udp" { address: string; port: number; }; - read(buffer: Buffer): number; get format(): "buffer" set format(value: "buffer") } diff --git a/typings/global.d.ts b/typings/global.d.ts index e75d7f8841..caa579d73e 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -1,4 +1,5 @@ import System_ from "embedded:io/system" +import "embedded:provider/builtin-device" declare global { // NOTE: `System` is non-standard and temporary to support the IO examples. Breaking changes are possible. From 37055ec7efa74356b6f5c106faca6de51a1383e5 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sat, 3 May 2025 09:55:32 -0400 Subject: [PATCH 22/23] Adjust for changes to io since initial PR --- examples/io/listener/httpserver/options/webpage.js | 2 +- examples/io/tcp/websocketclient/websocketclient.js | 7 +++++-- test262 | 1 - typings/embedded_network/http/server.d.ts | 3 ++- typings/embedded_network/http/server/options/webpage.d.ts | 2 +- typings/embedded_network/websocket/client.d.ts | 2 ++ 6 files changed, 11 insertions(+), 6 deletions(-) delete mode 160000 test262 diff --git a/examples/io/listener/httpserver/options/webpage.js b/examples/io/listener/httpserver/options/webpage.js index a32a7b67b9..796a9f2e4a 100644 --- a/examples/io/listener/httpserver/options/webpage.js +++ b/examples/io/listener/httpserver/options/webpage.js @@ -44,7 +44,7 @@ export default { } else throw new Error("unsupported data type"); - response.headers.set("content-type", route.contentType ?? this.route.contentType ?? "text/html"); + response.headers.set("content-type", route.contentType ?? "text/html"); response.status = this.route.status ?? 200; this.respond(response); }, diff --git a/examples/io/tcp/websocketclient/websocketclient.js b/examples/io/tcp/websocketclient/websocketclient.js index db50f02efc..f39ef390ad 100644 --- a/examples/io/tcp/websocketclient/websocketclient.js +++ b/examples/io/tcp/websocketclient/websocketclient.js @@ -235,7 +235,7 @@ class WebSocketClient { if (options.mask) { const mask = options.mask; Logical.xor(data, mask, count); - if (this.#data) { + if (this.#data) { switch (count & 3) { case 1: options.mask = Uint8Array.of(mask[1], mask[2], mask[3], mask[0]); @@ -402,6 +402,9 @@ class WebSocketClient { return; const opcode = options.tag & 0x0F; + if (options.mask) { + Logical.xor(control.buffer, options.mask.buffer); + } try { this.#options.onControl?.call(this, opcode, control.buffer); if (!this.#socket) @@ -561,7 +564,7 @@ class WebSocketClient { break; } } - #onError() { + #onError(error) { this.close(); if (this.#options.close) this.#options.onClose?.call(this); diff --git a/test262 b/test262 deleted file mode 160000 index 0add42b556..0000000000 --- a/test262 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0add42b556ee5bb4ec64aa82d2e234375f39fd2f diff --git a/typings/embedded_network/http/server.d.ts b/typings/embedded_network/http/server.d.ts index 3e6d09b4ef..b3daae1537 100644 --- a/typings/embedded_network/http/server.d.ts +++ b/typings/embedded_network/http/server.d.ts @@ -35,7 +35,8 @@ declare module "embedded:network/http/server" { export default class HTTPServer { constructor(options: HTTPServerOptions); - close(): void + close(): void; + get port(): number; } } \ No newline at end of file diff --git a/typings/embedded_network/http/server/options/webpage.d.ts b/typings/embedded_network/http/server/options/webpage.d.ts index 3b44f66d44..d197815ca0 100644 --- a/typings/embedded_network/http/server/options/webpage.d.ts +++ b/typings/embedded_network/http/server/options/webpage.d.ts @@ -3,7 +3,7 @@ declare module "embedded:network/http/server/options/webpage" { import type { Buffer } from "embedded:io/_common"; export interface HTTPServerRouteWebPage extends HTTPServerRoute { - msg: Buffer | string; + data: Buffer | string; contentType?: string; headers?: Map; status?: number; diff --git a/typings/embedded_network/websocket/client.d.ts b/typings/embedded_network/websocket/client.d.ts index 22b8026138..faf2cf1224 100644 --- a/typings/embedded_network/websocket/client.d.ts +++ b/typings/embedded_network/websocket/client.d.ts @@ -46,6 +46,8 @@ declare module "embedded:network/websocket/client" { close(): void; read(count?: number): ArrayBuffer | undefined; write(message: Buffer, options?: WebSocketClientWriteOptions): number; + get format(): "number" | "buffer"; + set format(value: "number" | "buffer"); static readonly text: 1; static readonly binary: 2; From 188fc2418381c281f6c4e1692dcb92e822e3b261 Mon Sep 17 00:00:00 2001 From: cmidgley Date: Sat, 3 May 2025 10:27:04 -0400 Subject: [PATCH 23/23] Minor cleanup for PR --- examples/io/tcp/websocket/WebSocket.js | 3 +-- examples/io/tcp/websocketclient/websocketclient.js | 4 ++-- examples/io/tcp/websocketsclient/config.js | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/io/tcp/websocket/WebSocket.js b/examples/io/tcp/websocket/WebSocket.js index d706ecc5e3..a6364c07b2 100644 --- a/examples/io/tcp/websocket/WebSocket.js +++ b/examples/io/tcp/websocket/WebSocket.js @@ -310,5 +310,4 @@ class WebSocket { } } -export default WebSocket; - +export default WebSocket; \ No newline at end of file diff --git a/examples/io/tcp/websocketclient/websocketclient.js b/examples/io/tcp/websocketclient/websocketclient.js index f39ef390ad..00803630ec 100644 --- a/examples/io/tcp/websocketclient/websocketclient.js +++ b/examples/io/tcp/websocketclient/websocketclient.js @@ -235,7 +235,7 @@ class WebSocketClient { if (options.mask) { const mask = options.mask; Logical.xor(data, mask, count); - if (this.#data) { + if (this.#data) { switch (count & 3) { case 1: options.mask = Uint8Array.of(mask[1], mask[2], mask[3], mask[0]); @@ -564,7 +564,7 @@ class WebSocketClient { break; } } - #onError(error) { + #onError() { this.close(); if (this.#options.close) this.#options.onClose?.call(this); diff --git a/examples/io/tcp/websocketsclient/config.js b/examples/io/tcp/websocketsclient/config.js index 99096592ca..c69d256c39 100644 --- a/examples/io/tcp/websocketsclient/config.js +++ b/examples/io/tcp/websocketsclient/config.js @@ -28,4 +28,4 @@ globalThis.device = Object.freeze({ } }, }, -}, true); +}, true); \ No newline at end of file