jq79 0.5.11 → 0.5.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@ export type ReactiveDeepData<T> = T & {
10
10
  $effect: (run: () => void, alsoWakenBy?: Record<string, any>[]) => Unsubscribe;
11
11
  $dispose: () => void;
12
12
  };
13
+ export declare const $toRaw: <T>(value: T) => T;
13
14
  export declare const untracked: <T>(fn: () => T) => T;
14
15
  export declare const ALSO_WAKEN_BY: unique symbol;
15
16
  export declare const $reactive: <T extends Record<string, any>>(data: T) => ReactiveDeepData<T>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jq79",
3
- "version": "0.5.11",
3
+ "version": "0.5.13",
4
4
  "description": "Mini reactive component library: single-file components, Svelte-style setup scripts, fine-grained proxy reactivity. Single-file build, zero dependencies.",
5
5
  "keywords": [
6
6
  "reactive",
@@ -64,6 +64,7 @@
64
64
  "test:coverage": "vitest run --coverage",
65
65
  "site": "node scripts/build-site.mjs",
66
66
  "site.dev": "node scripts/site-dev.mjs",
67
+ "benchmark": "node scripts/run-benchmark.mjs",
67
68
  "prepublishOnly": "npm test && npm run build"
68
69
  },
69
70
  "peerDependencies": {
@@ -82,6 +83,7 @@
82
83
  "jsdom": "^29.1.1",
83
84
  "marked": "^18.0.6",
84
85
  "marked-highlight": "^2.2.4",
86
+ "playwright": "^1.56.1",
85
87
  "sass": "^1.101.0",
86
88
  "tsup": "^8.5.1",
87
89
  "typescript": "^7.0.2",
package/src/jq79.ts CHANGED
@@ -1,12 +1,12 @@
1
1
 
2
2
  import { $, $$, $create, sanitizeHTML, allowedHosts } from "./dom"
3
3
  import type { AllowUrl } from "./dom"
4
- import { $reactive, untracked, createEffectScope, ALSO_WAKEN_BY } from "./reactive"
4
+ import { $reactive, $toRaw, untracked, createEffectScope, ALSO_WAKEN_BY } from "./reactive"
5
5
  import type { ReactiveDeepData, EffectScope } from "./reactive"
6
6
  import { transformSetupScript, transformFactoryScript, parsePropsPattern, parseFactoryProps, type PropDecl } from "./transform"
7
7
 
8
8
  export { $, $$, $create } from "./dom"
9
- export { $reactive } from "./reactive"
9
+ export { $reactive, $toRaw } from "./reactive"
10
10
 
11
11
  // the package version, substituted at build time (tsup/vitest `define`, read
12
12
  // from package.json - releases bump it there and nowhere else). The typeof
@@ -3025,7 +3025,7 @@ export const parseComponent = (component: string): Component79 => new Component7
3025
3025
  // library helpers injected into setup scripts. They behave like extra
3026
3026
  // globals: a same-named scope property (render data or a top-level
3027
3027
  // declaration) shadows them
3028
- const SETUP_HELPERS: Record<string, any> = { $, $$, $create, $reactive, Component79 }
3028
+ const SETUP_HELPERS: Record<string, any> = { $, $$, $create, $reactive, $toRaw, Component79 }
3029
3029
 
3030
3030
  // the hot-reload handshake. jq79/dev serves a classic script that sets the flag
3031
3031
  // below; classic scripts run before deferred module ones, so the flag is always
package/src/reactive.ts CHANGED
@@ -54,7 +54,12 @@ const pathsOverlap = (a: string, b: string): boolean =>
54
54
  // what it wraps, the nesting compounds until the process stops responding
55
55
  const RAW = Symbol("jq79.raw")
56
56
 
57
- const toRaw = <T>(value: T): T => {
57
+ // a free function rather than a method on the store, because the store API is
58
+ // served from the root proxy alone (see storeApi): `store.$toRaw()` would work
59
+ // and `store.user.$toRaw()` would not, which is the case callers actually have.
60
+ // The RAW symbol travels on every proxy at every depth, so this works anywhere.
61
+ // What it returns is the real object, not a copy: writes to it notify nobody
62
+ export const $toRaw = <T>(value: T): T => {
58
63
  let raw: any = value
59
64
  while (raw !== null && typeof raw === "object" && raw[RAW]) raw = raw[RAW]
60
65
  return raw
@@ -173,7 +178,7 @@ export const $reactive = <T extends Record<string, any>>(data: T): ReactiveDeepD
173
178
  }
174
179
 
175
180
  // the reactive view of `raw`, created on demand. Callers must hand it a raw
176
- // object (see toRaw at both call sites): wrapping a proxy is what compounds
181
+ // object (see $toRaw at both call sites): wrapping a proxy is what compounds
177
182
  const wrap = (raw: Record<string, any>, path: string): Record<string, any> => {
178
183
  const cached = proxies.get(raw)
179
184
  if (cached) return cached
@@ -206,7 +211,7 @@ export const $reactive = <T extends Record<string, any>>(data: T): ReactiveDeepD
206
211
  return value
207
212
  }
208
213
 
209
- const raw = toRaw(value)
214
+ const raw = $toRaw(value)
210
215
  return isWrappable(raw) ? wrap(raw, dotKey) : raw
211
216
  },
212
217
  set(target, key: string, value, receiver) {
@@ -226,7 +231,7 @@ export const $reactive = <T extends Record<string, any>>(data: T): ReactiveDeepD
226
231
  // that `list = [list[1], list[0]]` doesn't write proxies back into the
227
232
  // data. Reads re-wrap it, from the cache, as the very same proxy. A
228
233
  // whole store assigned in is the exception: it stays as it is
229
- const stored = isStore(value) ? value : toRaw(value)
234
+ const stored = isStore(value) ? value : $toRaw(value)
230
235
  const isNewKey = !Object.prototype.hasOwnProperty.call(target, key)
231
236
  // a primitive write that changes nothing notifies nobody: it's what
232
237
  // lets an effect write the value it just read (a normalizing
@@ -269,7 +274,7 @@ export const $reactive = <T extends Record<string, any>>(data: T): ReactiveDeepD
269
274
  return proxy
270
275
  }
271
276
 
272
- const reactive = wrap(toRaw(data), "") as ReactiveDeepData<T>
277
+ const reactive = wrap($toRaw(data), "") as ReactiveDeepData<T>
273
278
 
274
279
  // a store handed in with the data (a prop, or render data) is bridged here
275
280
  // rather than on first read, so a listener registered before anything reads
@@ -277,7 +282,7 @@ export const $reactive = <T extends Record<string, any>>(data: T): ReactiveDeepD
277
282
  // lands, and descending would mean walking whatever else was handed in - a
278
283
  // highlighter, an API client - to its leaves. A store sitting deeper is
279
284
  // bridged when the read that reaches it wraps its parent
280
- Object.entries(toRaw(data)).forEach(([key, value]) => {
285
+ Object.entries($toRaw(data)).forEach(([key, value]) => {
281
286
  if (isStore(value)) bridge(value, key)
282
287
  })
283
288