@gjsify/xmlhttprequest 0.4.21 → 0.4.22

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.
package/lib/esm/index.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import e from"gi://GLib?version=2.0";import t from"system";import n from"@gjsify/fetch";let r=0;var FakeBlob=class{_tmpPath;type;size;constructor(e,t){this.type=e,this.size=t}async arrayBuffer(){if(this._tmpPath){let[t,n]=e.file_get_contents(this._tmpPath);if(t)return n.buffer}return new ArrayBuffer(0)}async text(){return new TextDecoder().decode(await this.arrayBuffer())}stream(){let e=this;return new ReadableStream({async start(t){let n=await e.arrayBuffer();t.enqueue(new Uint8Array(n)),t.close()}})}};function guessExt(e){let t=e.toLowerCase();return t.endsWith(`.png`)?`.png`:t.endsWith(`.jpg`)||t.endsWith(`.jpeg`)?`.jpg`:t.endsWith(`.gif`)?`.gif`:t.endsWith(`.svg`)?`.svg`:t.endsWith(`.ttf`)?`.ttf`:t.endsWith(`.otf`)?`.otf`:t.endsWith(`.woff`)?`.woff`:t.endsWith(`.woff2`)?`.woff2`:t.endsWith(`.mp3`)?`.mp3`:t.endsWith(`.wav`)?`.wav`:t.endsWith(`.ogg`)?`.ogg`:t.endsWith(`.tmx`)||t.endsWith(`.xml`)?`.xml`:t.endsWith(`.json`)?`.json`:`.bin`}function guessMime(e){let t=e.toLowerCase();return t.endsWith(`.png`)?`image/png`:t.endsWith(`.jpg`)||t.endsWith(`.jpeg`)?`image/jpeg`:t.endsWith(`.gif`)?`image/gif`:t.endsWith(`.svg`)?`image/svg+xml`:t.endsWith(`.ttf`)?`font/truetype`:t.endsWith(`.otf`)?`font/otf`:t.endsWith(`.woff`)?`font/woff`:t.endsWith(`.woff2`)?`font/woff2`:t.endsWith(`.mp3`)?`audio/mpeg`:t.endsWith(`.wav`)?`audio/wav`:t.endsWith(`.ogg`)?`audio/ogg`:t.endsWith(`.json`)?`application/json`:`application/octet-stream`}async function readFileUrl(t){let n=e.filename_from_uri(t)[0],[r,i]=e.file_get_contents(n);if(!r)throw Error(`XMLHttpRequest: cannot read file ${n}`);let a=i,o=new Uint8Array(a.byteLength);return o.set(a),o.buffer}function writeToTmp(t,n){let i=e.build_filenamev([e.get_tmp_dir(),`gjsify-blob-${r++}${n}`]);return e.file_set_contents(i,t),i}var XMLHttpRequest=class{UNSENT=0;OPENED=1;HEADERS_RECEIVED=2;LOADING=3;DONE=4;readyState=0;status=0;statusText=``;response=null;responseText=``;responseType=``;responseURL=``;timeout=0;withCredentials=!1;onloadstart=null;onprogress=null;onload=null;onloadend=null;onerror=null;onabort=null;ontimeout=null;onreadystatechange=null;_url=``;_method=`GET`;_aborted=!1;_listeners={};open(e,t,n=!0){this._method=e.toUpperCase(),this._url=t,this._aborted=!1,this.readyState=this.OPENED}setRequestHeader(e,t){}overrideMimeType(e){}send(r){let i=this._url,a=this.responseType,o=globalThis.__GJSIFY_DEBUG_XHR===!0;if(i.startsWith(`/`)&&!i.startsWith(`//`)){let n=t.programPath??t.programInvocationName??``;n&&(i=`file://${e.path_get_dirname(n)}${this._url}`,o&&console.log(`[xmlhttprequest] rewrite ${this._url} → ${i}`))}o&&console.log(`[xmlhttprequest] ${this._method} ${i} responseType=${a}`);let doFetch=()=>i.startsWith(`file://`)?readFileUrl(i):n(i,{method:this._method}).then(e=>(o&&console.log(`[xmlhttprequest] fetch ok ${i} status=${e.status}`),this.status=e.status===0?200:e.status,this.statusText=e.statusText||`OK`,this.responseURL=e.url||i,e.arrayBuffer()));this.readyState=this.LOADING,this._emit(`loadstart`,{loaded:0,total:0,lengthComputable:!1}),Promise.resolve().then(doFetch).then(e=>{if(this._aborted)return;this.status===0&&(this.status=200),this.statusText||=`OK`,this.readyState=this.DONE;let t=new Uint8Array(e),n=t.byteLength;if(this._emit(`progress`,{loaded:n,total:n,lengthComputable:!0}),a===`blob`||a===``){let e=writeToTmp(t,guessExt(i)),r=new FakeBlob(guessMime(i),n);r._tmpPath=e,this.response=r}else a===`arraybuffer`?this.response=e:a===`json`?this.response=JSON.parse(new TextDecoder().decode(t)):(this.responseText=new TextDecoder().decode(t),this.response=this.responseText);this._emit(`load`,{target:this,loaded:n,total:n,lengthComputable:!0}),this._emit(`loadend`,{target:this,loaded:n,total:n,lengthComputable:!0}),this.onreadystatechange&&this.onreadystatechange({})}).catch(e=>{this._aborted||(console.warn(`[xmlhttprequest] ${this._method} ${i} — ${e?.message??e}`),this.readyState=this.DONE,this._emit(`error`,{error:e}),this._emit(`loadend`,{}))})}abort(){this._aborted=!0,this.readyState=this.DONE,this._emit(`abort`,{}),this._emit(`loadend`,{})}addEventListener(e,t){(this._listeners[e]??=[]).push(t)}removeEventListener(e,t){this._listeners[e]=(this._listeners[e]??[]).filter(e=>e!==t)}getResponseHeader(e){return null}getAllResponseHeaders(){return``}_emit(e,t){let n=this[`on`+e];typeof n==`function`&&n.call(this,{type:e,...t});for(let n of this._listeners[e]??[])n.call(this,{type:e,...t})}};function installObjectURLSupport(){if(typeof URL.createObjectURL!=`function`||URL.__gjsify_objecturl!==!0){let t=new Map;URL.createObjectURL=function(e){if(e._tmpPath){let n=`file://${e._tmpPath}`;return t.set(n,e._tmpPath),n}return console.warn(`[createObjectURL] received non-FakeBlob — cannot create file:// URL`),`file:///dev/null`},URL.revokeObjectURL=function(n){let r=t.get(n);if(r){try{let t=e.build_filenamev([r]);e.unlink(t)}catch{}t.delete(n)}},URL.__gjsify_objecturl=!0}}export{FakeBlob,XMLHttpRequest,installObjectURLSupport};
1
+ import"./_virtual/_rolldown/runtime.js";import e from"gi://GLib?version=2.0";import t from"system";import n from"@gjsify/fetch";let r=0;var FakeBlob=class{_tmpPath;type;size;constructor(e,t){this.type=e,this.size=t}async arrayBuffer(){if(this._tmpPath){let[t,n]=e.file_get_contents(this._tmpPath);if(t)return n.buffer}return new ArrayBuffer(0)}async text(){return new TextDecoder().decode(await this.arrayBuffer())}stream(){let e=this;return new ReadableStream({async start(t){let n=await e.arrayBuffer();t.enqueue(new Uint8Array(n)),t.close()}})}};function guessExt(e){let t=e.toLowerCase();return t.endsWith(`.png`)?`.png`:t.endsWith(`.jpg`)||t.endsWith(`.jpeg`)?`.jpg`:t.endsWith(`.gif`)?`.gif`:t.endsWith(`.svg`)?`.svg`:t.endsWith(`.ttf`)?`.ttf`:t.endsWith(`.otf`)?`.otf`:t.endsWith(`.woff`)?`.woff`:t.endsWith(`.woff2`)?`.woff2`:t.endsWith(`.mp3`)?`.mp3`:t.endsWith(`.wav`)?`.wav`:t.endsWith(`.ogg`)?`.ogg`:t.endsWith(`.tmx`)||t.endsWith(`.xml`)?`.xml`:t.endsWith(`.json`)?`.json`:`.bin`}function guessMime(e){let t=e.toLowerCase();return t.endsWith(`.png`)?`image/png`:t.endsWith(`.jpg`)||t.endsWith(`.jpeg`)?`image/jpeg`:t.endsWith(`.gif`)?`image/gif`:t.endsWith(`.svg`)?`image/svg+xml`:t.endsWith(`.ttf`)?`font/truetype`:t.endsWith(`.otf`)?`font/otf`:t.endsWith(`.woff`)?`font/woff`:t.endsWith(`.woff2`)?`font/woff2`:t.endsWith(`.mp3`)?`audio/mpeg`:t.endsWith(`.wav`)?`audio/wav`:t.endsWith(`.ogg`)?`audio/ogg`:t.endsWith(`.json`)?`application/json`:`application/octet-stream`}async function readFileUrl(t){let n=e.filename_from_uri(t)[0],[r,i]=e.file_get_contents(n);if(!r)throw Error(`XMLHttpRequest: cannot read file ${n}`);let a=i,o=new Uint8Array(a.byteLength);return o.set(a),o.buffer}function writeToTmp(t,n){let i=e.build_filenamev([e.get_tmp_dir(),`gjsify-blob-${r++}${n}`]);return e.file_set_contents(i,t),i}var XMLHttpRequest=class{UNSENT=0;OPENED=1;HEADERS_RECEIVED=2;LOADING=3;DONE=4;readyState=0;status=0;statusText=``;response=null;responseText=``;responseType=``;responseURL=``;timeout=0;withCredentials=!1;onloadstart=null;onprogress=null;onload=null;onloadend=null;onerror=null;onabort=null;ontimeout=null;onreadystatechange=null;_url=``;_method=`GET`;_aborted=!1;_listeners={};open(e,t,n=!0){this._method=e.toUpperCase(),this._url=t,this._aborted=!1,this.readyState=this.OPENED}setRequestHeader(e,t){}overrideMimeType(e){}send(r){let i=this._url,a=this.responseType,o=globalThis.__GJSIFY_DEBUG_XHR===!0;if(i.startsWith(`/`)&&!i.startsWith(`//`)){let n=t.programPath??t.programInvocationName??``;n&&(i=`file://${e.path_get_dirname(n)}${this._url}`,o&&console.log(`[xmlhttprequest] rewrite ${this._url} → ${i}`))}o&&console.log(`[xmlhttprequest] ${this._method} ${i} responseType=${a}`);let doFetch=()=>i.startsWith(`file://`)?readFileUrl(i):n(i,{method:this._method}).then(e=>(o&&console.log(`[xmlhttprequest] fetch ok ${i} status=${e.status}`),this.status=e.status===0?200:e.status,this.statusText=e.statusText||`OK`,this.responseURL=e.url||i,e.arrayBuffer()));this.readyState=this.LOADING,this._emit(`loadstart`,{loaded:0,total:0,lengthComputable:!1}),Promise.resolve().then(doFetch).then(e=>{if(this._aborted)return;this.status===0&&(this.status=200),this.statusText||=`OK`,this.readyState=this.DONE;let t=new Uint8Array(e),n=t.byteLength;if(this._emit(`progress`,{loaded:n,total:n,lengthComputable:!0}),a===`blob`||a===``){let e=writeToTmp(t,guessExt(i)),r=new FakeBlob(guessMime(i),n);r._tmpPath=e,this.response=r}else a===`arraybuffer`?this.response=e:a===`json`?this.response=JSON.parse(new TextDecoder().decode(t)):(this.responseText=new TextDecoder().decode(t),this.response=this.responseText);this._emit(`load`,{target:this,loaded:n,total:n,lengthComputable:!0}),this._emit(`loadend`,{target:this,loaded:n,total:n,lengthComputable:!0}),this.onreadystatechange&&this.onreadystatechange({})}).catch(e=>{this._aborted||(console.warn(`[xmlhttprequest] ${this._method} ${i} — ${e?.message??e}`),this.readyState=this.DONE,this._emit(`error`,{error:e}),this._emit(`loadend`,{}))})}abort(){this._aborted=!0,this.readyState=this.DONE,this._emit(`abort`,{}),this._emit(`loadend`,{})}addEventListener(e,t){(this._listeners[e]??=[]).push(t)}removeEventListener(e,t){this._listeners[e]=(this._listeners[e]??[]).filter(e=>e!==t)}getResponseHeader(e){return null}getAllResponseHeaders(){return``}_emit(e,t){let n=this[`on`+e];typeof n==`function`&&n.call(this,{type:e,...t});for(let n of this._listeners[e]??[])n.call(this,{type:e,...t})}};function installObjectURLSupport(){let t=URL;if(typeof t.createObjectURL!=`function`||t.__gjsify_objecturl!==!0){let n=new Map;t.createObjectURL=function(e){if(e._tmpPath){let t=`file://${e._tmpPath}`;return n.set(t,e._tmpPath),t}return console.warn(`[createObjectURL] received non-FakeBlob — cannot create file:// URL`),`file:///dev/null`},t.revokeObjectURL=function(t){let r=n.get(t);if(r){try{let t=e.build_filenamev([r]);e.unlink(t)}catch{}n.delete(t)}},t.__gjsify_objecturl=!0}}export{FakeBlob,XMLHttpRequest,installObjectURLSupport};
@@ -1 +1 @@
1
- import{XMLHttpRequest as e,installObjectURLSupport as t}from"./index.js";globalThis.XMLHttpRequest===void 0&&(globalThis.XMLHttpRequest=e),t();
1
+ import{XMLHttpRequest as e,installObjectURLSupport as t}from"./index.js";const n=globalThis;n.XMLHttpRequest===void 0&&(n.XMLHttpRequest=e),t();
package/lib/index.js CHANGED
@@ -262,6 +262,11 @@ export class XMLHttpRequest {
262
262
  return '';
263
263
  }
264
264
  _emit(type, event) {
265
+ // Look up the matching `on<type>` handler property. The Node-style
266
+ // `XMLHttpRequest` surface declares specific `onload` / `onerror` /
267
+ // `onprogress` / `ontimeout` / `onabort` / `onreadystatechange`
268
+ // properties, but indexing by computed `'on' + type` defeats
269
+ // structural typing. Cast through a typed view keyed on the union.
265
270
  const handler = this['on' + type];
266
271
  if (typeof handler === 'function')
267
272
  handler.call(this, { type, ...event });
@@ -269,17 +274,13 @@ export class XMLHttpRequest {
269
274
  fn.call(this, { type, ...event });
270
275
  }
271
276
  }
272
- // ---------------------------------------------------------------------------
273
- // URL.createObjectURL / revokeObjectURL
274
- // These patch the existing URL global (provided by @gjsify/url / @gjsify/node-globals).
275
- // HTMLImageElement.src natively handles file:// URLs via GLib.filename_from_uri + GdkPixbuf.
276
- // ---------------------------------------------------------------------------
277
277
  export function installObjectURLSupport() {
278
+ const urlPatch = URL;
278
279
  // Only install if not already a real implementation
279
- if (typeof URL.createObjectURL !== 'function' ||
280
- URL.__gjsify_objecturl !== true) {
280
+ if (typeof urlPatch.createObjectURL !== 'function' ||
281
+ urlPatch.__gjsify_objecturl !== true) {
281
282
  const _objectURLPaths = new Map();
282
- URL.createObjectURL = function (blob) {
283
+ urlPatch.createObjectURL = function (blob) {
283
284
  if (blob._tmpPath) {
284
285
  const url = `file://${blob._tmpPath}`;
285
286
  _objectURLPaths.set(url, blob._tmpPath);
@@ -289,7 +290,7 @@ export function installObjectURLSupport() {
289
290
  console.warn('[createObjectURL] received non-FakeBlob — cannot create file:// URL');
290
291
  return 'file:///dev/null';
291
292
  };
292
- URL.revokeObjectURL = function (url) {
293
+ urlPatch.revokeObjectURL = function (url) {
293
294
  const path = _objectURLPaths.get(url);
294
295
  if (path) {
295
296
  try {
@@ -303,6 +304,6 @@ export function installObjectURLSupport() {
303
304
  _objectURLPaths.delete(url);
304
305
  }
305
306
  };
306
- URL.__gjsify_objecturl = true;
307
+ urlPatch.__gjsify_objecturl = true;
307
308
  }
308
309
  }
package/lib/register.js CHANGED
@@ -3,8 +3,9 @@
3
3
  // On Node.js the alias layer routes this subpath to @gjsify/empty — the native
4
4
  // implementations are already present there.
5
5
  import { XMLHttpRequest, installObjectURLSupport } from './index.js';
6
- if (typeof globalThis.XMLHttpRequest === 'undefined') {
7
- globalThis.XMLHttpRequest = XMLHttpRequest;
6
+ const g = globalThis;
7
+ if (typeof g.XMLHttpRequest === 'undefined') {
8
+ g.XMLHttpRequest = XMLHttpRequest;
8
9
  }
9
10
  // Patch URL.createObjectURL / revokeObjectURL
10
11
  // URL is expected to be on globalThis already (via @gjsify/node-globals or @gjsify/url).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/xmlhttprequest",
3
- "version": "0.4.21",
3
+ "version": "0.4.22",
4
4
  "description": "XMLHttpRequest and URL.createObjectURL/revokeObjectURL for GJS — backed by @gjsify/fetch and GLib",
5
5
  "module": "lib/esm/index.js",
6
6
  "types": "lib/types/index.d.ts",
@@ -35,14 +35,14 @@
35
35
  "web-api"
36
36
  ],
37
37
  "dependencies": {
38
- "@girs/gio-2.0": "2.88.0-4.0.0-rc.15",
39
- "@girs/gjs": "4.0.0-rc.15",
40
- "@girs/glib-2.0": "2.88.0-4.0.0-rc.15",
41
- "@gjsify/fetch": "^0.4.21"
38
+ "@girs/gio-2.0": "2.88.0-4.0.1",
39
+ "@girs/gjs": "4.0.1",
40
+ "@girs/glib-2.0": "2.88.0-4.0.1",
41
+ "@gjsify/fetch": "^0.4.22"
42
42
  },
43
43
  "devDependencies": {
44
- "@gjsify/cli": "^0.4.21",
45
- "@types/node": "^25.6.2",
44
+ "@gjsify/cli": "^0.4.22",
45
+ "@types/node": "^25.9.1",
46
46
  "typescript": "^6.0.3"
47
47
  }
48
48
  }