xbintsc 0.3.16 → 0.3.25

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 (57) hide show
  1. package/dist/src/driver/bundler/graph.d.ts +2 -1
  2. package/dist/src/driver/bundler/graph.js +18 -3
  3. package/dist/src/driver/bundler/graph.js.map +1 -1
  4. package/dist/src/driver/bundler/merge.d.ts +2 -1
  5. package/dist/src/driver/bundler/merge.js +2 -2
  6. package/dist/src/driver/bundler/merge.js.map +1 -1
  7. package/dist/src/driver/compiler.js +2 -2
  8. package/dist/src/driver/compiler.js.map +1 -1
  9. package/dist/src/extensions/gui/html.d.ts +25 -0
  10. package/dist/src/extensions/gui/html.js +203 -0
  11. package/dist/src/extensions/gui/html.js.map +1 -0
  12. package/dist/src/extensions/gui/index.js +11 -0
  13. package/dist/src/extensions/gui/index.js.map +1 -1
  14. package/dist/src/extensions/registry.d.ts +29 -0
  15. package/dist/src/extensions/registry.js +14 -0
  16. package/dist/src/extensions/registry.js.map +1 -1
  17. package/dist/src/index.d.ts +1 -1
  18. package/dist/src/index.js.map +1 -1
  19. package/dist/src/lexer/scanner/identifiers.js +4 -12
  20. package/dist/src/lexer/scanner/identifiers.js.map +1 -1
  21. package/dist/tests/driver/bundler-resolve.test.d.ts +1 -0
  22. package/dist/tests/driver/bundler-resolve.test.js +230 -0
  23. package/dist/tests/driver/bundler-resolve.test.js.map +1 -0
  24. package/dist/tests/driver/modules.test.js +68 -0
  25. package/dist/tests/driver/modules.test.js.map +1 -1
  26. package/dist/tests/e2e/gui.test.js +210 -1
  27. package/dist/tests/e2e/gui.test.js.map +1 -1
  28. package/dist/tests/extensions/gui-index.test.d.ts +1 -0
  29. package/dist/tests/extensions/gui-index.test.js +49 -0
  30. package/dist/tests/extensions/gui-index.test.js.map +1 -0
  31. package/dist/tests/extensions/gui.test.d.ts +1 -0
  32. package/dist/tests/extensions/gui.test.js +177 -0
  33. package/dist/tests/extensions/gui.test.js.map +1 -0
  34. package/dist/tests/extensions/registry.test.js +36 -0
  35. package/dist/tests/extensions/registry.test.js.map +1 -1
  36. package/dist/tests/public-api.test.d.ts +1 -0
  37. package/dist/tests/public-api.test.js +31 -0
  38. package/dist/tests/public-api.test.js.map +1 -0
  39. package/package.json +1 -1
  40. package/runtime/ext_gui/document.cpp +90 -0
  41. package/runtime/ext_gui/document.h +23 -0
  42. package/runtime/ext_gui/dom.cpp +36 -0
  43. package/runtime/ext_gui/dom.h +7 -0
  44. package/runtime/ext_gui/dom_api.cpp +1247 -0
  45. package/runtime/ext_gui/dom_api.h +12 -0
  46. package/runtime/ext_gui/gui.cpp +49 -3
  47. package/runtime/ext_gui/gui_engine.h +54 -0
  48. package/runtime/ext_gui/script.cpp +63 -0
  49. package/runtime/ext_gui/window.cpp +60 -0
  50. package/src/driver/bundler/graph.ts +21 -2
  51. package/src/driver/bundler/merge.ts +3 -1
  52. package/src/driver/compiler.ts +2 -2
  53. package/src/extensions/gui/html.ts +236 -0
  54. package/src/extensions/gui/index.ts +11 -0
  55. package/src/extensions/registry.ts +39 -0
  56. package/src/index.ts +1 -1
  57. package/src/lexer/scanner/identifiers.ts +4 -11
@@ -0,0 +1,31 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as api from "../src/index.js";
3
+ describe("public API surface", () => {
4
+ it("re-exports the compiler pipeline", () => {
5
+ expect(typeof api.Scanner).toBe("function");
6
+ expect(typeof api.Parser).toBe("function");
7
+ expect(typeof api.bind).toBe("function");
8
+ expect(typeof api.generate).toBe("function");
9
+ expect(typeof api.hashText).toBe("function");
10
+ expect(api.TokenKind).toBeDefined();
11
+ expect(api.SymbolKind).toBeDefined();
12
+ expect(api.XT_UNDEFINED).toBeDefined();
13
+ expect(typeof api.numberLiteral).toBe("function");
14
+ expect(typeof api.booleanLiteral).toBe("function");
15
+ });
16
+ it("re-exports the extension system and driver", () => {
17
+ expect(typeof api.ExtensionRegistry).toBe("function");
18
+ expect(typeof api.createDefaultRegistry).toBe("function");
19
+ expect(api.coreExtension.name).toBe("core");
20
+ expect(api.nodeExtension.name).toBe("node");
21
+ expect(typeof api.bundledExtensions).toBe("function");
22
+ expect(api.bundledExtensions().length).toBeGreaterThan(0);
23
+ expect(typeof api.build).toBe("function");
24
+ expect(typeof api.compileString).toBe("function");
25
+ expect(typeof api.BuildCache).toBe("function");
26
+ expect(typeof api.findRuntimeDir).toBe("function");
27
+ expect(typeof api.findRuntimeLibrary).toBe("function");
28
+ expect(typeof api.resolveToolchain).toBe("function");
29
+ });
30
+ });
31
+ //# sourceMappingURL=public-api.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-api.test.js","sourceRoot":"","sources":["../../tests/public-api.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAC;AAEvC,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,CAAC,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,CAAC,OAAO,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,OAAO,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,GAAG,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1D,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,OAAO,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,CAAC,OAAO,GAAG,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xbintsc",
3
- "version": "0.3.16",
3
+ "version": "0.3.25",
4
4
  "description": "xbintsc - a TypeScript binary compiler (TypeScript -> LLVM IR -> native binary)",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,6 +24,8 @@ void XtDocument::collectStyleText(const Node *node, std::string *out) const {
24
24
 
25
25
  void XtDocument::load(const std::string &html, float viewportWidth, float viewportHeight) {
26
26
  root_ = xt_html_parse(html);
27
+ detached_.clear();
28
+ dirty_ = false;
27
29
  hover_ = nullptr;
28
30
  focus_ = nullptr;
29
31
  styles_.clear();
@@ -261,4 +263,92 @@ std::string XtDocument::toDebugString() const {
261
263
  return root_ == nullptr ? std::string() : xt_dom_to_string(root_.get());
262
264
  }
263
265
 
266
+ /* -- DOM mutation --------------------------------------------------------- */
267
+
268
+ Node *XtDocument::createElement(const std::string &tag) {
269
+ auto node = std::make_unique<Node>(NodeType::Element);
270
+ node->tag = tag;
271
+ Node *raw = node.get();
272
+ detached_[raw] = std::move(node);
273
+ return raw;
274
+ }
275
+
276
+ Node *XtDocument::createTextNode(const std::string &text) {
277
+ auto node = std::make_unique<Node>(NodeType::Text);
278
+ node->text = text;
279
+ Node *raw = node.get();
280
+ detached_[raw] = std::move(node);
281
+ return raw;
282
+ }
283
+
284
+ namespace {
285
+
286
+ /** Take ownership of a node that is either attached or sitting in the pool. */
287
+ std::unique_ptr<Node> takeNode(
288
+ Node *node, std::unordered_map<const Node *, std::unique_ptr<Node>> &pool) {
289
+ if (node->parent != nullptr) return node->parent->detachChild(node);
290
+ auto it = pool.find(node);
291
+ if (it == pool.end()) return nullptr;
292
+ std::unique_ptr<Node> owned = std::move(it->second);
293
+ pool.erase(it);
294
+ return owned;
295
+ }
296
+
297
+ } // namespace
298
+
299
+ Node *XtDocument::appendChild(Node *parent, Node *child) {
300
+ if (parent == nullptr || child == nullptr) return nullptr;
301
+ if (!parent->isElement() || child->isDocument() || child == root_.get()) return nullptr;
302
+ if (child->contains(parent)) return nullptr; /* reject cycles */
303
+ std::unique_ptr<Node> owned = takeNode(child, detached_);
304
+ if (owned == nullptr) return nullptr;
305
+ invalidate();
306
+ return parent->append(std::move(owned));
307
+ }
308
+
309
+ Node *XtDocument::insertBefore(Node *parent, Node *child, Node *reference) {
310
+ if (reference == nullptr) return appendChild(parent, child);
311
+ if (parent == nullptr || child == nullptr || child == reference) return child;
312
+ if (!parent->isElement() || child->isDocument() || child == root_.get()) return nullptr;
313
+ if (child->contains(parent)) return nullptr; /* reject cycles */
314
+ bool reference_is_child = false;
315
+ for (const std::unique_ptr<Node> &entry : parent->children) {
316
+ if (entry.get() == reference) {
317
+ reference_is_child = true;
318
+ break;
319
+ }
320
+ }
321
+ if (!reference_is_child) return nullptr;
322
+ std::unique_ptr<Node> owned = takeNode(child, detached_);
323
+ if (owned == nullptr) return nullptr;
324
+ invalidate();
325
+ return parent->insertChild(std::move(owned), reference);
326
+ }
327
+
328
+ bool XtDocument::removeChild(Node *parent, Node *child) {
329
+ if (parent == nullptr || child == nullptr || child->parent != parent) return false;
330
+ std::unique_ptr<Node> owned = parent->detachChild(child);
331
+ if (owned == nullptr) return false;
332
+ detached_[child] = std::move(owned);
333
+ invalidate();
334
+ return true;
335
+ }
336
+
337
+ Node *XtDocument::replaceChild(Node *parent, Node *newChild, Node *oldChild) {
338
+ if (parent == nullptr || oldChild == nullptr || oldChild->parent != parent) return nullptr;
339
+ if (newChild == oldChild) return newChild;
340
+ if (newChild != nullptr && !insertBefore(parent, newChild, oldChild)) return nullptr;
341
+ removeChild(parent, oldChild);
342
+ return newChild;
343
+ }
344
+
345
+ void XtDocument::detach(Node *node) {
346
+ if (node == nullptr || node == root_.get()) return;
347
+ if (node->parent != nullptr) {
348
+ std::unique_ptr<Node> owned = node->parent->detachChild(node);
349
+ if (owned != nullptr) detached_[node] = std::move(owned);
350
+ }
351
+ invalidate();
352
+ }
353
+
264
354
  } // namespace xtgui
@@ -63,6 +63,26 @@ class XtDocument {
63
63
  const Node *querySelector(const std::string &selectorText) const;
64
64
  /** Elements matching a CSS selector, in document order. */
65
65
  std::vector<const Node *> querySelectorAll(const std::string &selectorText) const;
66
+
67
+ /* -- DOM mutation (element handles) ------------------------------------ */
68
+ /** Create a detached element/text node owned by the document. */
69
+ Node *createElement(const std::string &tag);
70
+ Node *createTextNode(const std::string &text);
71
+ /** Move `child` under `parent` (from its current parent or the detached pool). */
72
+ Node *appendChild(Node *parent, Node *child);
73
+ Node *insertBefore(Node *parent, Node *child, Node *reference);
74
+ bool removeChild(Node *parent, Node *child);
75
+ Node *replaceChild(Node *parent, Node *newChild, Node *oldChild);
76
+ /** Release a node from the document entirely (still owned, detached). */
77
+ void detach(Node *node);
78
+
79
+ /** Mark the document as needing a restyle/relayout before the next paint. */
80
+ void invalidate() { dirty_ = true; }
81
+ bool takeDirty() {
82
+ bool was = dirty_;
83
+ dirty_ = false;
84
+ return was;
85
+ }
66
86
  /** Serialized DOM, for diagnostics. */
67
87
  std::string toDebugString() const;
68
88
 
@@ -72,6 +92,9 @@ class XtDocument {
72
92
  void updateDisplay();
73
93
 
74
94
  std::unique_ptr<Node> root_;
95
+ /** Detached nodes (created or removed) stay alive here so handles remain valid. */
96
+ std::unordered_map<const Node *, std::unique_ptr<Node>> detached_;
97
+ bool dirty_ = false;
75
98
  StyleSheet sheet_;
76
99
  std::unordered_map<const Node *, XtStyle> styles_; // target (cascade)
77
100
  std::unordered_map<const Node *, XtStyle> display_; // after transitions
@@ -37,6 +37,42 @@ Node *Node::append(std::unique_ptr<Node> child) {
37
37
  return raw;
38
38
  }
39
39
 
40
+ std::unique_ptr<Node> Node::detachChild(Node *child) {
41
+ for (auto it = children.begin(); it != children.end(); ++it) {
42
+ if (it->get() == child) {
43
+ std::unique_ptr<Node> owned = std::move(*it);
44
+ children.erase(it);
45
+ owned->parent = nullptr;
46
+ return owned;
47
+ }
48
+ }
49
+ return nullptr;
50
+ }
51
+
52
+ Node *Node::insertChild(std::unique_ptr<Node> child, Node *reference) {
53
+ child->parent = this;
54
+ Node *raw = child.get();
55
+ if (reference == nullptr) {
56
+ children.push_back(std::move(child));
57
+ return raw;
58
+ }
59
+ for (auto it = children.begin(); it != children.end(); ++it) {
60
+ if (it->get() == reference) {
61
+ children.insert(it, std::move(child));
62
+ return raw;
63
+ }
64
+ }
65
+ children.push_back(std::move(child));
66
+ return raw;
67
+ }
68
+
69
+ bool Node::contains(const Node *node) const {
70
+ for (const Node *current = node; current != nullptr; current = current->parent) {
71
+ if (current == this) return true;
72
+ }
73
+ return false;
74
+ }
75
+
40
76
  Node *Node::addElement(const std::string &tagName) {
41
77
  auto node = std::make_unique<Node>(NodeType::Element);
42
78
  node->tag = tagName;
@@ -49,6 +49,13 @@ struct Node {
49
49
  Node *addText(const std::string &data);
50
50
  Node *append(std::unique_ptr<Node> child);
51
51
 
52
+ /** Detach a direct child, transferring ownership to the caller. */
53
+ std::unique_ptr<Node> detachChild(Node *child);
54
+ /** Insert `child` before `reference` (append when `reference` is nullptr). */
55
+ Node *insertChild(std::unique_ptr<Node> child, Node *reference);
56
+ /** True when `node` is this node or a descendant of it. */
57
+ bool contains(const Node *node) const;
58
+
52
59
  /** First element child (skips text), or NULL. */
53
60
  Node *firstElementChild() const;
54
61
  /** Total number of element children with the same tag, and this node's index. */