dsh-unlag 1.9.99 → 1.9.101

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.
Files changed (2) hide show
  1. package/index.js +33 -9
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -830,12 +830,19 @@ function buttonAllowed(req) {
830
830
  return false
831
831
  }
832
832
  const origin = typeof req?.headers?.origin === 'string' ? req.headers.origin.trim().toLowerCase() : ''
833
- if (origin === 'null') return false
833
+ // An opaque origin belongs to a document this machine did not open, and an origin that cannot
834
+ // be read is one this check cannot judge. Both are refused, and both say so: a refusal nobody
835
+ // can find afterwards is the kind of silence that makes a wrong answer look like a right one.
836
+ if (origin === 'null') {
837
+ log('refused a press from an opaque origin')
838
+ return false
839
+ }
834
840
  if (origin !== '') {
835
841
  let originSite = ''
836
842
  try {
837
843
  originSite = new URL(origin).host.toLowerCase() // ui-copy-ignore
838
844
  } catch {
845
+ log(`refused a press from an origin that is not an address: ${oneLine(origin, 200)}`)
839
846
  return false
840
847
  }
841
848
  if (originSite !== site) {
@@ -1936,8 +1943,10 @@ function serveButton(ctx, controller, config) {
1936
1943
  * A page on any site can post to a local address without asking first, and a log is
1937
1944
  * evidence: a made-up outcome must not get in. The header the page's own script sends
1938
1945
  * makes the request one a browser has to ask about first, and this app never agrees.
1946
+ * The same address check the press uses applies here too: the log is the record a press
1947
+ * leaves behind, so a page that may not press may not write into it either.
1939
1948
  */
1940
- if (typeof req?.headers?.[BUTTON_HEADER] !== 'string') return sendJson(res, 403, { status: 'forbidden' })
1949
+ if (buttonAllowed(req) === false) return sendJson(res, 403, { status: 'forbidden' })
1941
1950
  let query = ''
1942
1951
  try {
1943
1952
  query = new URL(String(req?.url ?? ''), 'http://x').searchParams.toString()
@@ -2042,14 +2051,23 @@ export function apply(ctx, config) {
2042
2051
  * root is installed and no saved file applies anything by itself.
2043
2052
  */
2044
2053
  const syncWatching = () => {
2045
- if (settingsOf(config ?? {}).autoReload !== true) return
2046
- if (controller.available() === false) {
2054
+ // Automatic reloading is an extra, and the press is the feature: anything that goes wrong
2055
+ // while setting a watch up is said in one line and left off, never turned into a plugin that
2056
+ // did not load.
2057
+ try {
2058
+ if (settingsOf(config ?? {}).autoReload !== true) return
2059
+ if (controller.available() === false) {
2060
+ closeAll(globalThis[WATCHER_KEY])
2061
+ globalThis[WATCHER_KEY] = null
2062
+ return
2063
+ }
2064
+ if (globalThis[WATCHER_KEY] !== null) return
2065
+ globalThis[WATCHER_KEY] = controller.startWatching()
2066
+ } catch (error) {
2047
2067
  closeAll(globalThis[WATCHER_KEY])
2048
2068
  globalThis[WATCHER_KEY] = null
2049
- return
2069
+ log(`cannot watch for saved plugin changes: ${error?.message ?? error}; a press still works`)
2050
2070
  }
2051
- if (globalThis[WATCHER_KEY] !== null) return
2052
- globalThis[WATCHER_KEY] = controller.startWatching()
2053
2071
  }
2054
2072
  // Printed on every start so a reader of the log knows which action applies a change: a person
2055
2073
  // pressing the button, never this plugin, and never a restart of the app.
@@ -2064,8 +2082,14 @@ export function apply(ctx, config) {
2064
2082
  }
2065
2083
  if (typeof ctx.on === 'function') {
2066
2084
  ctx.on('internal/service', (service) => {
2067
- if (service === 'hmr') syncWatching()
2068
- if (service === 'clientModules') syncBundles()
2085
+ // A service event is dispatched by the app itself; an exception here would travel back into
2086
+ // whatever asked, so each answer is kept to its own line.
2087
+ try {
2088
+ if (service === 'hmr') syncWatching()
2089
+ if (service === 'clientModules') syncBundles()
2090
+ } catch (error) {
2091
+ log(`cannot follow the ${oneLine(service, 40)} service: ${error?.message ?? error}`)
2092
+ }
2069
2093
  })
2070
2094
  }
2071
2095
  globalThis[ROUTES_KEY] = serveButton(ctx, controller, config ?? {})
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-unlag",
3
- "version": "1.9.99",
3
+ "version": "1.9.101",
4
4
  "type": "module",
5
5
  "description": "A press applies plugin edits right away and brings a laggy interface back; automatic reloading stays off unless you turn it on, so the press is the only trigger, and nothing restarts.",
6
6
  "license": "MIT",