Skip to content

Commit 069d181

Browse files
committed
HTTP compression with opt-in caching
`http`: `HttpDirs` now have opt-in support for caching resolved paths, eliminating iteration and IO on cache hits. Added `HttpCompressor`, with the following features: - Selects an appropriate compression algorithm based on `accept-encoding` declared by a client in its request. - Performs encoding as appropriate, falling back on a plain response if client and server don't agree on an encoding. - Has opt-in support for caching compressed file responses. In combination with caching in `HttpDirs`, this allows us to serve files with no IO or re-compression after the first hit. - Supported algorithms: Zstd, Brotli, Gzip, Deflate. - At the time of writing, Zstd is not yet available in Deno. In Bun, `HttpCompressor` should be used for dynamically-generated responses even when the caching feature is not utilized. Deno has built-in auto-compression of dynamic responses. Breaking: renamed: `HttpFile..res` → `HttpFile..response`. Breaking: removed: - `HttpFile..setType` - `HttpFile..setHeaders` `HttpFile..opt` now always converts headers to `Headers` and sets the guessed content type, if any, in those headers. Added `HEADER_NAME_ACCEPT_ENCODING`. Added `HEADER_NAME_CONTENT_ENCODING`. Every class containing code which constructs a `Response` instance now allows to provide a custom `Response` class by overriding its `.Res` getter. This was already supported in some places before; now it's supported consistently. --- `http_live.mjs`: Breaking: renamed: `LiveBroad..res` → `LiveBroad..response`. --- `obj.mjs`: Added: - `resource` - `resources` - `deinit` --- `path.mjs`: Breaking: - Dropped `Paths..cwdEmp` (now hardcoded). - Dropped `Paths..cwdRel` (now hardcoded). - Dropped `Paths..parRel` (now hardcoded). - `isDirLike` now returns `false` for empty paths. - `Paths..ext` now performs much better, but no longer supports cases where `Paths..dirSep` is overridden with a non-slash, similarly to `Paths..hasExt`. We might be making similar changes in other places later. Added: - `SEP_ENV` - `EXT_SEP` - `CWD_REL` - `PAR_REL` --- `lang.mjs`: Breaking: the functions `hasOwn`, `hasOwnEnum`, `hasInherited`, and `hasMeth` now return `false` if the key is not a string or symbol. Previously, it was possible, for example, to pass a number and get `true` if the target had a string-keyed field matching that number. --- `dom_reg.mjs`: `TAG_TO_CLS` is now a pure expression, and can be elided by bundlers if this module is imported but not used. --- `dom_shim.mjs`: `PH_GLOB` is now a pure expression, and can be elided by bundlers if this module is imported but not used.
1 parent 741650b commit 069d181

52 files changed

Lines changed: 1274 additions & 733 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@
1111
!/doc
1212
!/docs
1313
!/test
14-
/prompts.md
14+
!/misc
15+
/misc/*
16+
!/misc/*.mjs

cli.mjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,14 +204,18 @@ export const TERM_ESC_CLEAR_SOFT = TERM_ESC_RESET
204204
// Clear screen AND scrollback.
205205
export const TERM_ESC_CLEAR_HARD = TERM_ESC_CUP + TERM_ESC_RESET + TERM_ESC_ERASE3
206206

207+
let ENC
208+
207209
let ARR_CLEAR_SOFT
208210
export function arrClearSoft() {
209-
return ARR_CLEAR_SOFT ??= new TextEncoder().encode(TERM_ESC_CLEAR_SOFT)
211+
ENC ??= new TextEncoder()
212+
return ARR_CLEAR_SOFT ??= ENC.encode(TERM_ESC_CLEAR_SOFT)
210213
}
211214

212215
let ARR_CLEAR_HARD
213216
export function arrClearHard() {
214-
return ARR_CLEAR_HARD ??= new TextEncoder().encode(TERM_ESC_CLEAR_HARD)
217+
ENC ??= new TextEncoder()
218+
return ARR_CLEAR_HARD ??= ENC.encode(TERM_ESC_CLEAR_HARD)
215219
}
216220

217221
export function timed(tag, fun) {

doc/cmd_doc_util.mjs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,27 @@ import * as l from '../lang.mjs'
22
import * as o from '../obj.mjs'
33

44
export class Strict extends l.Emp {
5-
constructor() {
6-
super()
7-
return new Proxy(this, PH)
8-
}
5+
// eslint-disable-next-line constructor-super
6+
constructor() {return new Proxy(super(), PH)}
97
}
108

11-
export const PH = l.Emp()
9+
export const PH = {
10+
__proto__: null,
1211

13-
PH.get = function get(tar, key, pro) {
14-
if (l.hasOwn(tar, key)) return tar[key]
12+
get(tar, key, pro) {
13+
if (l.hasOwn(tar, key)) return tar[key]
1514

16-
/*
17-
For async/await. JS engines don't try the `.has` trap for this property,
18-
they just `.get` it.
19-
*/
20-
if (key === `then`) return tar[key]
15+
/*
16+
For async/await. JS engines don't try the `.has` trap for this property,
17+
they just `.get` it.
18+
*/
19+
if (key === `then`) return tar[key]
2120

22-
// For compatibility with `memGet`.
23-
const desc = o.descIn(tar, key)
24-
if (!desc) throw l.errIn(tar, key)
25-
if (desc.get) return desc.get.call(pro)
21+
// For compatibility with `memGet`.
22+
const desc = o.descIn(tar, key)
23+
if (!desc) throw l.errIn(tar, key)
24+
if (desc.get) return desc.get.call(pro)
2625

27-
return desc.value
26+
return desc.value
27+
},
2828
}

doc/http_bun_readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ async function respond(req) {
2828
const path = new URL(req.url).pathname
2929

3030
return (
31-
(await DIRS.resolveSiteFileWithNotFound(path))?.res() ||
31+
(await DIRS.resolveSiteFileWithNotFound(path))?.response() ||
3232
new Response(`not found`, {status: 404})
3333
)
3434
}

doc/http_deno_readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ async function respond(req) {
2828
const path = new URL(req.url).pathname
2929

3030
return (
31-
(await DIRS.resolveSiteFileWithNotFound(path))?.res() ||
31+
(await DIRS.resolveSiteFileWithNotFound(path))?.response() ||
3232
new Response(`not found`, {status: 404})
3333
)
3434
}

doc/lang/isDict.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1-
True for a "plain object" created via `{...}` or `Object.create(null)`. False for any other input, including instances of any class other than `Object`.
1+
True for a "plain object" created in any of the following ways:
2+
* `{...someFields}`
3+
* `{__proto__: null, ...someFields}`
4+
* `Object.create(null)`
5+
6+
False for any other input, including instances of any class other than `Object`, or even for `Object.create(Object.create(null))`.
27

38
See {{link lang isRec}} for a more general definition of a non-iterable object.

docs/cli_readme.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
CLI args:
2424

2525
```js
26-
import * as cl from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/cli.mjs'
26+
import * as cl from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/cli.mjs'
2727

2828
const cli = cl.Flag.os()
2929

@@ -34,15 +34,15 @@ console.log(...cli.args)
3434
Console clearing:
3535

3636
```js
37-
import * as cl from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/cli.mjs'
37+
import * as cl from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/cli.mjs'
3838

3939
cl.emptty()
4040
```
4141

4242
Clearing the console only once, before running your code:
4343

4444
```js
45-
import 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/cli_emptty.mjs'
45+
import 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/cli_emptty.mjs'
4646
```
4747

4848
## API
@@ -83,6 +83,6 @@ The following APIs are exported but undocumented. Check [cli.mjs](../cli.mjs).
8383
* [`const TERM_ESC_RESET`](../cli.mjs#L198)
8484
* [`const TERM_ESC_CLEAR_SOFT`](../cli.mjs#L202)
8585
* [`const TERM_ESC_CLEAR_HARD`](../cli.mjs#L205)
86-
* [`function arrClearSoft`](../cli.mjs#L208)
87-
* [`function arrClearHard`](../cli.mjs#L213)
88-
* [`function timed`](../cli.mjs#L217)
86+
* [`function arrClearSoft`](../cli.mjs#L210)
87+
* [`function arrClearHard`](../cli.mjs#L216)
88+
* [`function timed`](../cli.mjs#L221)

docs/coll_readme.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Port and rework of https://github.com/mitranim/jol.
2626
## Usage
2727

2828
```js
29-
import * as c from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/coll.mjs'
29+
import * as c from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/coll.mjs'
3030
```
3131

3232
## API
@@ -101,8 +101,8 @@ Links: [source](../coll.mjs#L100); [test/example](../test/coll_test.mjs#L218).
101101
Variant of [#`Bmap`](#class-bmap) with support for key and value checks. Subclasses must override methods `.reqKey` and `.reqVal`. These methods are automatically called by `.set`. Method `.reqKey` must validate and return the given key, and method `.reqVal` must validate and return the given value. Use type assertions provided by [`lang`](lang_readme.md).
102102

103103
```js
104-
import * as l from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/lang.mjs'
105-
import * as c from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/coll.mjs'
104+
import * as l from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/lang.mjs'
105+
import * as c from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/coll.mjs'
106106

107107
class StrNatMap extends c.TypedMap {
108108
reqKey(key) {return l.reqStr(key)}
@@ -242,7 +242,7 @@ Differences and advantages over `Array`:
242242
The overhead of the wrapper is insignificant.
243243

244244
```js
245-
import * as c from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/coll.mjs'
245+
import * as c from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/coll.mjs'
246246

247247
console.log(new c.Vec())
248248
// Vec{Symbol(val): []}

docs/dom_readme.md

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
## Usage
1212

1313
```js
14-
import * as d from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/dom.mjs'
14+
import * as d from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/dom.mjs'
1515
```
1616

1717
## API
@@ -41,34 +41,34 @@ The following APIs are exported but undocumented. Check [dom.mjs](../dom.mjs).
4141
* [`function isFile`](../dom.mjs#L32)
4242
* [`function reqFile`](../dom.mjs#L33)
4343
* [`function optFile`](../dom.mjs#L34)
44-
* [`function eventKill`](../dom.mjs#L48)
45-
* [`function eventStop`](../dom.mjs#L54)
46-
* [`function isEventModified`](../dom.mjs#L61)
47-
* [`function eventDispatch`](../dom.mjs#L65)
48-
* [`function eventListen`](../dom.mjs#L69)
49-
* [`class ListenRef`](../dom.mjs#L74)
50-
* [`function nodeShow`](../dom.mjs#L106)
51-
* [`function nodeHide`](../dom.mjs#L107)
52-
* [`function nodeRemove`](../dom.mjs#L108)
53-
* [`function nodeSel`](../dom.mjs#L109)
54-
* [`function nodeSelAll`](../dom.mjs#L110)
55-
* [`function isConnected`](../dom.mjs#L111)
56-
* [`function isDisconnected`](../dom.mjs#L112)
57-
* [`function copyToClipboard`](../dom.mjs#L124)
58-
* [`function selectText`](../dom.mjs#L143)
59-
* [`function ancestor`](../dom.mjs#L154)
60-
* [`function findAncestor`](../dom.mjs#L161)
61-
* [`function descendant`](../dom.mjs#L178)
62-
* [`function findDescendant`](../dom.mjs#L180)
63-
* [`function descendants`](../dom.mjs#L185)
64-
* [`function findNextSibling`](../dom.mjs#L198)
65-
* [`function nextSibling`](../dom.mjs#L206)
66-
* [`function findPrevSibling`](../dom.mjs#L208)
67-
* [`function prevSibling`](../dom.mjs#L216)
68-
* [`function MixNode`](../dom.mjs#L222)
69-
* [`class MixinNode`](../dom.mjs#L224)
70-
* [`const PARENT_NODE`](../dom.mjs#L240)
71-
* [`function MixChild`](../dom.mjs#L256)
72-
* [`class MixinChild`](../dom.mjs#L258)
73-
* [`function MixChildCon`](../dom.mjs#L313)
74-
* [`class MixinChildCon`](../dom.mjs#L315)
44+
* [`function eventKill`](../dom.mjs#L36)
45+
* [`function eventStop`](../dom.mjs#L42)
46+
* [`function isEventModified`](../dom.mjs#L49)
47+
* [`function eventDispatch`](../dom.mjs#L53)
48+
* [`function eventListen`](../dom.mjs#L57)
49+
* [`class ListenRef`](../dom.mjs#L62)
50+
* [`function nodeShow`](../dom.mjs#L94)
51+
* [`function nodeHide`](../dom.mjs#L95)
52+
* [`function nodeRemove`](../dom.mjs#L96)
53+
* [`function nodeSel`](../dom.mjs#L97)
54+
* [`function nodeSelAll`](../dom.mjs#L98)
55+
* [`function isConnected`](../dom.mjs#L99)
56+
* [`function isDisconnected`](../dom.mjs#L100)
57+
* [`function copyToClipboard`](../dom.mjs#L102)
58+
* [`function selectText`](../dom.mjs#L121)
59+
* [`function ancestor`](../dom.mjs#L132)
60+
* [`function findAncestor`](../dom.mjs#L139)
61+
* [`function descendant`](../dom.mjs#L156)
62+
* [`function findDescendant`](../dom.mjs#L158)
63+
* [`function descendants`](../dom.mjs#L163)
64+
* [`function findNextSibling`](../dom.mjs#L176)
65+
* [`function nextSibling`](../dom.mjs#L184)
66+
* [`function findPrevSibling`](../dom.mjs#L186)
67+
* [`function prevSibling`](../dom.mjs#L194)
68+
* [`function MixNode`](../dom.mjs#L200)
69+
* [`class MixinNode`](../dom.mjs#L202)
70+
* [`const PARENT_NODE`](../dom.mjs#L218)
71+
* [`function MixChild`](../dom.mjs#L234)
72+
* [`class MixinChild`](../dom.mjs#L236)
73+
* [`function MixChildCon`](../dom.mjs#L291)
74+
* [`class MixinChildCon`](../dom.mjs#L293)

docs/dom_reg_readme.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
Example mockup for a pushstate link.
2828

2929
```js
30-
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/dom_reg.mjs'
30+
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/dom_reg.mjs'
3131

3232
// Immediately ready for use. Tag is automatically set to `a-btn`.
3333
// The mixin `MixReg` enables automatic registration on instantiation.
@@ -66,7 +66,7 @@ Apps which use server-side rendering and client-side upgrading of custom element
6666
Instead, use `dr.reg`, which is also used internally by `MixReg`. This is simply a shortcut for using the [#default registry](#class-reg) provided by this module.
6767

6868
```js
69-
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/dom_reg.mjs'
69+
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/dom_reg.mjs'
7070

7171
class Btn extends HTMLButtonElement {
7272
/*
@@ -89,13 +89,13 @@ console.log(elem.outerHTML)
8989

9090
### `function reg`
9191

92-
Links: [source](../dom_reg.mjs#L143); [test/example](../test/dom_reg_test.mjs#L15).
92+
Links: [source](../dom_reg.mjs#L148); [test/example](../test/dom_reg_test.mjs#L15).
9393

9494
Shortcut for calling `Reg.main.reg`. Takes a custom element class and idempotently registers it, automatically deriving the custom element tag name _and_ the base tag for `extends`.
9595

9696
### `class Reg`
9797

98-
Links: [source](../dom_reg.mjs#L145); [test/example](../test/dom_reg_test.mjs#L21).
98+
Links: [source](../dom_reg.mjs#L150); [test/example](../test/dom_reg_test.mjs#L21).
9999

100100
Registry for custom DOM element classes. Automatically derives tag name from class name, using salting when necessary to avoid collisions. Supports idempotent registration which can be safely called in an element constructor. Allows immediate registration, deferred registration, or a mix of those.
101101

@@ -106,7 +106,7 @@ For browser-only code, prefer the mixin `MixReg` from the same module which is e
106106
Simple usage:
107107

108108
```js
109-
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/dom_reg.mjs'
109+
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/dom_reg.mjs'
110110

111111
class Btn extends HTMLButtonElement {
112112
/*
@@ -126,7 +126,7 @@ document.body.append(new Btn())
126126
You can unset the default definer to defer registration:
127127

128128
```js
129-
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.78/dom_reg.mjs'
129+
import * as dr from 'https://cdn.jsdelivr.net/npm/@mitranim/js@0.1.79/dom_reg.mjs'
130130

131131
dr.Reg.main.setDefiner()
132132

@@ -147,15 +147,15 @@ dr.Reg.main.setDefiner(customElements)
147147

148148
The following APIs are exported but undocumented. Check [dom_reg.mjs](../dom_reg.mjs).
149149

150-
* [`const TAG_TO_CLS`](../dom_reg.mjs#L9)
150+
* [`const TAG_TO_CLS`](../dom_reg.mjs#L8)
151151
* [`const CLS_TO_TAG`](../dom_reg.mjs#L95)
152-
* [`function clsLocalName`](../dom_reg.mjs#L108)
153-
* [`function MixReg`](../dom_reg.mjs#L128)
154-
* [`class MixinReg`](../dom_reg.mjs#L130)
155-
* [`function setDefiner`](../dom_reg.mjs#L141)
156-
* [`function isDefiner`](../dom_reg.mjs#L250)
157-
* [`function optDefiner`](../dom_reg.mjs#L251)
158-
* [`function reqDefiner`](../dom_reg.mjs#L252)
159-
* [`function onlyDefiner`](../dom_reg.mjs#L253)
160-
* [`function isCustomName`](../dom_reg.mjs#L258)
161-
* [`function reqCustomName`](../dom_reg.mjs#L262)
152+
* [`function clsLocalName`](../dom_reg.mjs#L113)
153+
* [`function MixReg`](../dom_reg.mjs#L133)
154+
* [`class MixinReg`](../dom_reg.mjs#L135)
155+
* [`function setDefiner`](../dom_reg.mjs#L146)
156+
* [`function isDefiner`](../dom_reg.mjs#L255)
157+
* [`function optDefiner`](../dom_reg.mjs#L256)
158+
* [`function reqDefiner`](../dom_reg.mjs#L257)
159+
* [`function onlyDefiner`](../dom_reg.mjs#L258)
160+
* [`function isCustomName`](../dom_reg.mjs#L263)
161+
* [`function reqCustomName`](../dom_reg.mjs#L267)

0 commit comments

Comments
 (0)