xbintsc 0.5.37 → 0.5.41

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 (166) hide show
  1. package/dist/src/cli/help.d.ts +1 -1
  2. package/dist/src/codegen/generator/module.js +23 -7
  3. package/dist/src/codegen/generator/module.js.map +1 -1
  4. package/dist/src/codegen/generator/state.js +1 -0
  5. package/dist/src/codegen/generator/state.js.map +1 -1
  6. package/dist/src/codegen/generator/tables.js +1 -0
  7. package/dist/src/codegen/generator/tables.js.map +1 -1
  8. package/dist/src/driver/bundler/deferred.d.ts +63 -0
  9. package/dist/src/driver/bundler/deferred.js +279 -0
  10. package/dist/src/driver/bundler/deferred.js.map +1 -0
  11. package/dist/src/driver/bundler/merge.js +214 -2
  12. package/dist/src/driver/bundler/merge.js.map +1 -1
  13. package/dist/src/driver/runtime-objects.d.ts +1 -1
  14. package/dist/src/driver/runtime-objects.js +1 -0
  15. package/dist/src/driver/runtime-objects.js.map +1 -1
  16. package/dist/src/driver/version.d.ts +1 -1
  17. package/dist/src/driver/version.js +1 -1
  18. package/dist/src/extensions/gui/html.js +98 -15
  19. package/dist/src/extensions/gui/html.js.map +1 -1
  20. package/dist/src/extensions/gui/index.js +1 -0
  21. package/dist/src/extensions/gui/index.js.map +1 -1
  22. package/dist/src/extensions/gui/three.d.ts +4 -3
  23. package/dist/src/extensions/gui/three.js +4 -3
  24. package/dist/src/extensions/gui/three.js.map +1 -1
  25. package/dist/tests/codegen/closures.test.js +7 -0
  26. package/dist/tests/codegen/closures.test.js.map +1 -1
  27. package/dist/tests/e2e/compile-objects-classes.test.js +31 -0
  28. package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
  29. package/dist/tests/e2e/gui-canvas-state.test.d.ts +9 -0
  30. package/dist/tests/e2e/gui-canvas-state.test.js +297 -0
  31. package/dist/tests/e2e/gui-canvas-state.test.js.map +1 -0
  32. package/dist/tests/e2e/gui-draw-perf.test.d.ts +22 -0
  33. package/dist/tests/e2e/gui-draw-perf.test.js +405 -0
  34. package/dist/tests/e2e/gui-draw-perf.test.js.map +1 -0
  35. package/dist/tests/e2e/gui-perf.test.d.ts +23 -0
  36. package/dist/tests/e2e/gui-perf.test.js +283 -0
  37. package/dist/tests/e2e/gui-perf.test.js.map +1 -0
  38. package/dist/tests/e2e/gui-script-import-order.test.d.ts +10 -0
  39. package/dist/tests/e2e/gui-script-import-order.test.js +169 -0
  40. package/dist/tests/e2e/gui-script-import-order.test.js.map +1 -0
  41. package/dist/tests/e2e/gui-webgl.test.js +4 -4
  42. package/dist/tests/e2e/gui-webgl.test.js.map +1 -1
  43. package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.d.ts +8 -0
  44. package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.js +336 -0
  45. package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.js.map +1 -0
  46. package/dist/tests/e2e/gui-webgl2-shadow.test.d.ts +10 -0
  47. package/dist/tests/e2e/gui-webgl2-shadow.test.js +108 -0
  48. package/dist/tests/e2e/gui-webgl2-shadow.test.js.map +1 -0
  49. package/dist/tests/e2e/url.test.d.ts +6 -0
  50. package/dist/tests/e2e/url.test.js +114 -0
  51. package/dist/tests/e2e/url.test.js.map +1 -0
  52. package/dist/tests/extensions/gui.test.js +45 -10
  53. package/dist/tests/extensions/gui.test.js.map +1 -1
  54. package/doc/gui/api.md +28 -2
  55. package/doc/gui/canvas.md +110 -27
  56. package/doc/gui/known-issues.md +32 -10
  57. package/doc/gui/rendering.md +77 -0
  58. package/doc/gui/runtime.md +18 -3
  59. package/doc/gui/webgl.md +58 -29
  60. package/doc/gui-scripts.md +19 -19
  61. package/doc/gui.md +43 -9
  62. package/doc/implemented/fetch.md +5 -0
  63. package/doc/implemented/modules.md +13 -0
  64. package/doc/implemented/stdlib.md +17 -0
  65. package/doc/unimplemented/deviations.md +1 -0
  66. package/doc/zh-CN/gui/api.md +25 -2
  67. package/doc/zh-CN/gui/canvas.md +95 -26
  68. package/doc/zh-CN/gui/known-issues.md +21 -4
  69. package/doc/zh-CN/gui/rendering.md +59 -0
  70. package/doc/zh-CN/gui/runtime.md +13 -3
  71. package/doc/zh-CN/gui/webgl.md +30 -8
  72. package/doc/zh-CN/gui-scripts.md +14 -13
  73. package/doc/zh-CN/gui.md +32 -8
  74. package/doc/zh-CN/implemented/fetch.md +4 -0
  75. package/doc/zh-CN/implemented/modules.md +10 -0
  76. package/doc/zh-CN/implemented/stdlib.md +15 -0
  77. package/doc/zh-CN/unimplemented/deviations.md +1 -0
  78. package/package.json +7 -7
  79. package/runtime/ext_gui/browser.cpp +3 -1
  80. package/runtime/ext_gui/canvas.cpp +135 -89
  81. package/runtime/ext_gui/canvas.h +116 -0
  82. package/runtime/ext_gui/canvas_clip.cpp +143 -0
  83. package/runtime/ext_gui/canvas_composite.cpp +241 -0
  84. package/runtime/ext_gui/canvas_coverage.cpp +241 -0
  85. package/runtime/ext_gui/canvas_gradient.cpp +41 -4
  86. package/runtime/ext_gui/canvas_image_data.cpp +4 -0
  87. package/runtime/ext_gui/canvas_internal.h +34 -9
  88. package/runtime/ext_gui/canvas_raster.cpp +207 -178
  89. package/runtime/ext_gui/canvas_shadow.cpp +161 -0
  90. package/runtime/ext_gui/canvas_stroke.cpp +37 -9
  91. package/runtime/ext_gui/canvas_style.cpp +59 -0
  92. package/runtime/ext_gui/canvas_text.cpp +140 -0
  93. package/runtime/ext_gui/css.h +7 -0
  94. package/runtime/ext_gui/css_sheet.cpp +22 -0
  95. package/runtime/ext_gui/document.cpp +25 -1
  96. package/runtime/ext_gui/document.h +8 -0
  97. package/runtime/ext_gui/dom_api_canvas.cpp +16 -1
  98. package/runtime/ext_gui/dom_api_canvas_image.cpp +9 -0
  99. package/runtime/ext_gui/dom_api_canvas_state.cpp +217 -0
  100. package/runtime/ext_gui/dom_api_internal.h +36 -37
  101. package/runtime/ext_gui/dom_api_offscreen.cpp +213 -0
  102. package/runtime/ext_gui/dom_api_proto.cpp +18 -0
  103. package/runtime/ext_gui/dom_api_webgl.cpp +29 -9
  104. package/runtime/ext_gui/dom_api_webgl2.cpp +33 -1
  105. package/runtime/ext_gui/dom_api_webgl_internal.h +58 -0
  106. package/runtime/ext_gui/dom_api_webgl_source.cpp +18 -0
  107. package/runtime/ext_gui/gradient_values.cpp +12 -1
  108. package/runtime/ext_gui/gui.cpp +5 -0
  109. package/runtime/ext_gui/gui_canvas.cpp +4 -0
  110. package/runtime/ext_gui/gui_engine.h +32 -0
  111. package/runtime/ext_gui/gui_events.cpp +182 -58
  112. package/runtime/ext_gui/gui_media.cpp +3 -0
  113. package/runtime/ext_gui/image.cpp +69 -0
  114. package/runtime/ext_gui/image_bitmap_browser.cpp +11 -0
  115. package/runtime/ext_gui/layout.cpp +4 -0
  116. package/runtime/ext_gui/paint.cpp +19 -0
  117. package/runtime/ext_gui/paint_background.cpp +18 -1
  118. package/runtime/ext_gui/perf.cpp +171 -0
  119. package/runtime/ext_gui/perf.h +127 -0
  120. package/runtime/ext_gui/renderer.cpp +109 -41
  121. package/runtime/ext_gui/renderer.h +33 -9
  122. package/runtime/ext_gui/renderer_image.cpp +135 -65
  123. package/runtime/ext_gui/renderer_internal.h +15 -3
  124. package/runtime/ext_gui/renderer_text.cpp +24 -12
  125. package/runtime/ext_gui/script.cpp +31 -0
  126. package/runtime/ext_gui/style.cpp +101 -30
  127. package/runtime/ext_gui/style.h +6 -3
  128. package/runtime/ext_gui/style_print.cpp +7 -1
  129. package/runtime/ext_gui/text.cpp +23 -4
  130. package/runtime/ext_gui/text.h +29 -0
  131. package/runtime/ext_gui/text_cache.cpp +118 -0
  132. package/runtime/ext_gui/text_glyph_cache.cpp +100 -0
  133. package/runtime/ext_gui/webgl.h +48 -146
  134. package/runtime/ext_gui/webgl_blit.cpp +12 -1
  135. package/runtime/ext_gui/webgl_blit_depth.cpp +270 -0
  136. package/runtime/ext_gui/webgl_buffer.cpp +59 -1
  137. package/runtime/ext_gui/webgl_buffer_objects.cpp +106 -9
  138. package/runtime/ext_gui/webgl_clear.cpp +3 -0
  139. package/runtime/ext_gui/webgl_context.cpp +29 -3
  140. package/runtime/ext_gui/webgl_draw.cpp +75 -270
  141. package/runtime/ext_gui/webgl_draw_buffers.cpp +1 -0
  142. package/runtime/ext_gui/webgl_draw_setup.cpp +321 -0
  143. package/runtime/ext_gui/webgl_draw_state.h +130 -0
  144. package/runtime/ext_gui/webgl_glsl.h +3 -0
  145. package/runtime/ext_gui/webgl_glsl_scan.cpp +3 -8
  146. package/runtime/ext_gui/webgl_glsl_unroll.cpp +283 -0
  147. package/runtime/ext_gui/webgl_msl.cpp +4 -0
  148. package/runtime/ext_gui/webgl_objects.h +148 -0
  149. package/runtime/ext_gui/webgl_pipeline.cpp +8 -8
  150. package/runtime/ext_gui/webgl_program_internal.h +35 -0
  151. package/runtime/ext_gui/webgl_shader.cpp +34 -36
  152. package/runtime/ext_gui/webgl_webgl2.cpp +36 -0
  153. package/runtime/ext_gui/window.cpp +56 -1
  154. package/runtime/rt.h +3 -0
  155. package/runtime/xt_fetch/async.inc +60 -0
  156. package/runtime/xt_url_object.c +463 -0
  157. package/src/codegen/generator/module.ts +22 -7
  158. package/src/codegen/generator/state.ts +1 -0
  159. package/src/codegen/generator/tables.ts +1 -0
  160. package/src/driver/bundler/deferred.ts +351 -0
  161. package/src/driver/bundler/merge.ts +219 -2
  162. package/src/driver/runtime-objects.ts +1 -0
  163. package/src/driver/version.ts +1 -1
  164. package/src/extensions/gui/html.ts +100 -17
  165. package/src/extensions/gui/index.ts +1 -0
  166. package/src/extensions/gui/three.ts +4 -3
@@ -78,6 +78,7 @@ void WebGLContext::save_vertex_array() {
78
78
  void WebGLContext::load_vertex_array(const WebGLVertexArray *array) {
79
79
  for (int i = 0; i < kWebGLMaxAttribs; i++) attribs_[i] = array->attribs[i];
80
80
  bound_element_ = array->element_buffer;
81
+ attribs_version_ += 1;
81
82
  }
82
83
 
83
84
  void WebGLContext::bind_vertex_array(uint32_t id) {
@@ -238,6 +239,11 @@ bool WebGLContext::sampler_parameter(uint32_t id, int pname, int value) {
238
239
  else if (pname == GL_TEXTURE_MAG_FILTER) record->mag_filter = value;
239
240
  else if (pname == GL_TEXTURE_WRAP_S) record->wrap_s = value;
240
241
  else if (pname == GL_TEXTURE_WRAP_T) record->wrap_t = value;
242
+ else if (pname == GL_TEXTURE_COMPARE_MODE) {
243
+ record->compare_mode = value == GL_COMPARE_REF_TO_TEXTURE;
244
+ } else if (pname == GL_TEXTURE_COMPARE_FUNC) {
245
+ record->compare_func = value;
246
+ }
241
247
  if (record->gpu != nullptr && guidev::g_device != nullptr) {
242
248
  SDL_ReleaseGPUSampler(guidev::g_device, record->gpu);
243
249
  record->gpu = nullptr;
@@ -252,6 +258,10 @@ int WebGLContext::sampler_parameter_value(uint32_t id, int pname) {
252
258
  if (pname == GL_TEXTURE_MAG_FILTER) return record->mag_filter;
253
259
  if (pname == GL_TEXTURE_WRAP_S) return record->wrap_s;
254
260
  if (pname == GL_TEXTURE_WRAP_T) return record->wrap_t;
261
+ if (pname == GL_TEXTURE_COMPARE_MODE) {
262
+ return record->compare_mode ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
263
+ }
264
+ if (pname == GL_TEXTURE_COMPARE_FUNC) return record->compare_func;
255
265
  return 0;
256
266
  }
257
267
 
@@ -270,6 +280,32 @@ SDL_GPUSampler *WebGLContext::sampler_gpu(WebGLSampler *record) {
270
280
  /* A sampler object has no texture, so it cannot know how many levels exist;
271
281
  * textures created by this engine always carry a full mip chain. */
272
282
  info.max_lod = 1000.0f;
283
+ if (record->compare_mode) {
284
+ info.enable_compare = true;
285
+ switch (record->compare_func) {
286
+ case GL_NEVER:
287
+ info.compare_op = SDL_GPU_COMPAREOP_NEVER;
288
+ break;
289
+ case GL_LESS:
290
+ info.compare_op = SDL_GPU_COMPAREOP_LESS;
291
+ break;
292
+ case GL_EQUAL:
293
+ info.compare_op = SDL_GPU_COMPAREOP_EQUAL;
294
+ break;
295
+ case GL_GREATER:
296
+ info.compare_op = SDL_GPU_COMPAREOP_GREATER;
297
+ break;
298
+ case GL_NOTEQUAL:
299
+ info.compare_op = SDL_GPU_COMPAREOP_NOT_EQUAL;
300
+ break;
301
+ case GL_GEQUAL:
302
+ info.compare_op = SDL_GPU_COMPAREOP_GREATER_OR_EQUAL;
303
+ break;
304
+ default:
305
+ info.compare_op = SDL_GPU_COMPAREOP_LESS_OR_EQUAL;
306
+ break;
307
+ }
308
+ }
273
309
  record->gpu = SDL_CreateGPUSampler(guidev::g_device, &info);
274
310
  return record->gpu;
275
311
  }
@@ -15,6 +15,7 @@
15
15
 
16
16
  #include "inline_svg.h"
17
17
  #include "paint.h"
18
+ #include "perf.h"
18
19
  #include "text.h"
19
20
 
20
21
  static xt_value g_window_proto = XT_UNDEFINED;
@@ -72,10 +73,15 @@ static xt_value win_load_html(xt_value self, xt_value env, int32_t argc, xt_valu
72
73
  xt_gui_window_viewport(win, &width, &height);
73
74
  win->document->load(html, width, height);
74
75
  win->geometry.dirty = 1;
76
+ win->present_dirty = 1;
75
77
  /* Run the AOT-compiled `<script>` bodies now that the tree is parsed, so
76
78
  * `document.getElementById(...)` resolves, then settle the first layout. */
77
79
  xt_gui_run_scripts(win);
78
80
  xt_gui_flush_dom(win);
81
+ /* The document was replaced, so the frame loop must reconcile the media
82
+ * and canvas tables with it on the next frame. `loadHTML` already flushed
83
+ * the style/layout, so this is a sync request, not a restyle. */
84
+ win->sync_dirty = 1;
79
85
  }
80
86
  xt_object_set(self, xt_string_from_cstr("__xt_gui_html"), xt_string_from_cstr(html.c_str()));
81
87
  /* Painting the document is milestone M3b+; the parsed tree and computed
@@ -199,6 +205,7 @@ static xt_value win_set_background(xt_value self, xt_value env, int32_t argc, xt
199
205
  win->background[1] = color.g;
200
206
  win->background[2] = color.b;
201
207
  win->background[3] = color.a;
208
+ win->present_dirty = 1;
202
209
  }
203
210
  }
204
211
  xt_object_set(self, xt_string_from_cstr("__xt_gui_background"), text);
@@ -265,7 +272,10 @@ static xt_value win_advance(xt_value self, xt_value env, int32_t argc, xt_value
265
272
  XtGuiWindow *win = xt_gui_window_from_this(self);
266
273
  if (win == nullptr || win->document == nullptr) return XT_UNDEFINED;
267
274
  double ms = argc > 0 ? xt_to_number(xt_arg(argc, argv, 0)) : 0.0;
268
- if (win->document->advance(ms)) win->geometry.dirty = 1;
275
+ if (win->document->advance(ms)) {
276
+ win->geometry.dirty = 1;
277
+ win->present_dirty = 1;
278
+ }
269
279
  return XT_UNDEFINED;
270
280
  }
271
281
 
@@ -481,6 +491,51 @@ static xt_value win_stats(xt_value self, xt_value env, int32_t argc, xt_value *a
481
491
  xt_number(win != nullptr ? (double)win->node_order.size() : 0));
482
492
  xt_object_set(object, xt_string_from_cstr("listeners"),
483
493
  xt_number(win != nullptr ? (double)win->node_listeners.size() : 0));
494
+ /* -- renderer counters (see `perf.h`) ---------------------------------- */
495
+ /* The `*Ms` values describe the last completed frame; every other counter is
496
+ * cumulative (diff two calls to get the work one frame did). */
497
+ const xtgui::PerfTimings &ms = xtgui::g_perf_last;
498
+ xt_object_set(object, xt_string_from_cstr("frameMs"), xt_number(ms.frame));
499
+ xt_object_set(object, xt_string_from_cstr("restyleMs"), xt_number(ms.restyle));
500
+ xt_object_set(object, xt_string_from_cstr("layoutMs"), xt_number(ms.layout));
501
+ xt_object_set(object, xt_string_from_cstr("paintMs"), xt_number(ms.paint));
502
+ xt_object_set(object, xt_string_from_cstr("uploadMs"), xt_number(ms.upload));
503
+ xt_object_set(object, xt_string_from_cstr("drawMs"), xt_number(ms.draw));
504
+ const xtgui::PerfCounters &counters = xtgui::g_perf_total;
505
+ auto setCounter = [&object](const char *name, uint64_t value) {
506
+ xt_object_set(object, xt_string_from_cstr(name), xt_number((double)value));
507
+ };
508
+ setCounter("frames", counters.frames);
509
+ setCounter("presents", counters.presents);
510
+ setCounter("exposes", counters.exposes);
511
+ setCounter("deferred", counters.deferred);
512
+ setCounter("starvedFrames", counters.starvedFrames);
513
+ setCounter("skippedFrames", counters.skippedFrames);
514
+ setCounter("restyles", counters.restyles);
515
+ setCounter("restyleNodes", counters.restyleNodes);
516
+ setCounter("rulesEvaluated", counters.rulesEvaluated);
517
+ setCounter("mediaEvaluated", counters.mediaEvaluated);
518
+ setCounter("layouts", counters.layouts);
519
+ setCounter("layoutBoxes", counters.layoutBoxes);
520
+ setCounter("textShapeCalls", counters.textShapeCalls);
521
+ setCounter("textShapeHits", counters.textShapeHits);
522
+ setCounter("textCacheBytes", xtgui::xt_text_cache_bytes());
523
+ setCounter("textCacheEntries", xtgui::xt_text_cache_entries());
524
+ setCounter("paints", counters.paints);
525
+ setCounter("paintOps", counters.paintOps);
526
+ setCounter("drawRuns", counters.drawRuns);
527
+ setCounter("drawCalls", counters.drawCalls);
528
+ setCounter("uploadSubmits", counters.uploadSubmits);
529
+ setCounter("vertices", counters.vertices);
530
+ setCounter("syncNodes", counters.syncNodes);
531
+ setCounter("transitionFrames", counters.transitionFrames);
532
+ setCounter("canvasDraws", counters.canvasDraws);
533
+ setCounter("canvasUploads", counters.canvasUploads);
534
+ setCounter("canvasUploadBytes", counters.canvasUploadBytes);
535
+ setCounter("webglDraws", counters.webglDraws);
536
+ setCounter("webglPasses", counters.webglPasses);
537
+ setCounter("webglPipelineMisses", counters.webglPipelineMisses);
538
+ setCounter("webglBufferUploadBytes", counters.webglBufferUploadBytes);
484
539
  return object;
485
540
  }
486
541
 
package/runtime/rt.h CHANGED
@@ -305,6 +305,9 @@ xt_value xt_date_static(xt_value name, int32_t argc, xt_value *argv);
305
305
  xt_value xt_regexp_ctor(int32_t argc, xt_value *argv);
306
306
 
307
307
  /* -- node:url ------------------------------------------------------------- */
308
+ xt_value xt_url_ctor(int32_t argc, xt_value *argv);
309
+ /** Resolve a `fetch` reference to a filesystem path (file: URLs and relative paths). */
310
+ int xt_url_file_path(const char *url, char *out, size_t size);
308
311
  xt_value xt_url_path_to_file_url(int32_t argc, xt_value *argv);
309
312
  xt_value xt_url_file_url_to_path(int32_t argc, xt_value *argv);
310
313
 
@@ -201,6 +201,66 @@ static void xt_fetch_hop_complete(xt_async_job *job) {
201
201
 
202
202
  /* Main thread: validate the current URL and queue one exchange. */
203
203
  static void xt_fetch_start(xt_fetch_state *state) {
204
+ /* `file:` URLs and references with no scheme (a relative path) read a local
205
+ * file. This is what lets a compiled page load an asset from disk without an
206
+ * HTTP server; the response is built on this thread because a local read is
207
+ * already complete. */
208
+ char path[4096];
209
+ if (xt_url_file_path(state->url, path, sizeof(path))) {
210
+ if (strcmp(state->method, "GET") != 0 && strcmp(state->method, "HEAD") != 0) {
211
+ xt_fetch_state_reject(state, "fetch failed: file URLs only support GET or HEAD");
212
+ return;
213
+ }
214
+ FILE *file = fopen(path, "rb");
215
+ if (!file) {
216
+ xt_fetch_state_reject(state, "fetch failed: cannot read file");
217
+ return;
218
+ }
219
+ size_t capacity = 0;
220
+ size_t length = 0;
221
+ char *body = NULL;
222
+ char chunk[16384];
223
+ for (;;) {
224
+ size_t count = fread(chunk, 1, sizeof(chunk), file);
225
+ if (count > 0) {
226
+ if (length + count + 1 > capacity) {
227
+ capacity = (length + count + 1) * 2;
228
+ char *grown = (char *)realloc(body, capacity);
229
+ if (!grown) {
230
+ free(body);
231
+ fclose(file);
232
+ xt_fetch_state_reject(state, "fetch failed");
233
+ return;
234
+ }
235
+ body = grown;
236
+ }
237
+ memcpy(body + length, chunk, count);
238
+ length += count;
239
+ }
240
+ if (count < sizeof(chunk)) break;
241
+ }
242
+ fclose(file);
243
+
244
+ char href[4300];
245
+ if (path[0] == '/') {
246
+ snprintf(href, sizeof(href), "file://%s", path);
247
+ } else {
248
+ snprintf(href, sizeof(href), "file:///%s", path);
249
+ }
250
+ xt_value headers = xt_headers_new();
251
+ char lengthText[32];
252
+ snprintf(lengthText, sizeof(lengthText), "%zu", length);
253
+ xt_headers_set_raw(headers, "content-length", lengthText);
254
+ xt_headers_set_raw(headers, "content-type", "application/octet-stream");
255
+ size_t bodyLength = strcmp(state->method, "HEAD") == 0 ? 0 : length;
256
+ xt_value response = xt_response_new(headers, 200, "OK", href, body, bodyLength);
257
+ free(body);
258
+ xt_value promise = state->promise;
259
+ xt_fetch_state_free(state);
260
+ xt_promise_fulfill(promise, response);
261
+ return;
262
+ }
263
+
204
264
  xt_fetch_url parsed;
205
265
  if (xt_fetch_parse_url(state->url, &parsed) != 0) {
206
266
  xt_fetch_state_reject(state, "Failed to parse URL");