@lucent-lang/lucent 0.1.1 → 0.1.3

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 (31) hide show
  1. package/bin/lucent.cjs +2 -0
  2. package/dist/{bench-eEez4jhQ.js → bench-BLZugR80.js} +1 -1
  3. package/dist/{build-CpUjeHFz.js → build-C1Uct_mH.js} +1 -1
  4. package/dist/{build-check-BA1ZEp9s.js → build-check-hlYTmPRd.js} +1 -1
  5. package/dist/{check-BZx3FgI6.js → check-BksBP--n.js} +1 -1
  6. package/dist/cli.js +15 -11
  7. package/dist/{codes-D-6LxUqD.js → codes-B6AgFgAq.js} +24 -2
  8. package/dist/compiler.js +3 -3
  9. package/dist/{dashboard-CC-HXhcd.js → dashboard-CzOJghrS.js} +1 -1
  10. package/dist/{dev-DI5yL8zx.js → dev-CtaNF3sP.js} +3 -3
  11. package/dist/{explain-Byit07F-.js → explain-ImANcx5a.js} +1 -1
  12. package/dist/{pipeline-BM_VM2X_.js → pipeline-DXFTV3Mg.js} +21 -7
  13. package/dist/{project-BKNoTEEp.js → project-Bp9I-fLP.js} +254 -5
  14. package/dist/{sdk-coverage-iiv3JqMp.js → sdk-coverage-BpbKBG_O.js} +33 -4
  15. package/dist/{sdk-diff-ByJ1Gw-F.js → sdk-diff-BueKDJQB.js} +3 -3
  16. package/dist/{sdk-lock-BQn7IyRs.js → sdk-lock-CKLnZ0Wl.js} +2 -2
  17. package/dist/{sdk-prefetch-Bv2pNega.js → sdk-prefetch-rk6MuMe6.js} +2 -2
  18. package/dist/{sdk-search-CPGJm_Ne.js → sdk-search-U_2M81lq.js} +2 -2
  19. package/dist/{sdk-show-BUkLqRnA.js → sdk-show-DG6H40fp.js} +2 -2
  20. package/dist/{sdk-usage-0ZFMAYg1.js → sdk-usage-Cc7u1i0L.js} +1 -1
  21. package/dist/{src-ChnmWLwn.js → src-DMbXwPlK.js} +2209 -546
  22. package/lib/sdk/android.d.ts +12 -0
  23. package/lib/sdk/compose.d.ts +17 -4
  24. package/lib/sdk/ui.d.ts +21 -0
  25. package/package.json +1 -1
  26. package/runtime/cpp/lucent/platform/android.cpp +152 -16
  27. package/runtime/cpp/lucent/platform/android.h +79 -2
  28. package/runtime/cpp/lucent/platform/ios.h +7 -0
  29. package/runtime/cpp/lucent/platform/ios_ui.h +20 -0
  30. package/runtime/cpp/rn/LucentComponentView.mm +12 -0
  31. package/runtime/cpp/rn/LucentViewSizing.h +9 -1
@@ -1,4 +1,4 @@
1
- import { n as Explanations, r as docsUrl, t as Codes } from "./codes-D-6LxUqD.js";
1
+ import { n as Explanations, r as docsUrl, t as Codes } from "./codes-B6AgFgAq.js";
2
2
  import { n as lucentPackages, t as lucentPackageOf } from "./packages-CSmKeaAh.js";
3
3
  import { createRequire } from "node:module";
4
4
  import fs from "node:fs";
@@ -13,19 +13,23 @@ import { spawnSync } from "node:child_process";
13
13
  var CompileError = class extends Error {
14
14
  node;
15
15
  code;
16
- constructor(node, code, message) {
16
+ fix;
17
+ constructor(node, code, message, fix) {
17
18
  super(message);
18
19
  this.node = node;
19
20
  this.code = code;
21
+ this.fix = fix;
20
22
  }
21
23
  };
22
- function fail$2(node, code, message) {
23
- throw new CompileError(node, code, message);
24
+ function fail$2(node, code, message, fix) {
25
+ throw new CompileError(node, code, message, fix);
24
26
  }
25
27
  function toDiagnostic(e) {
28
+ const fix = e.fix ? { fix: e.fix } : {};
26
29
  if (!e.node) return {
27
30
  code: e.code,
28
- message: e.message
31
+ message: e.message,
32
+ ...fix
29
33
  };
30
34
  const sf = e.node.getSourceFile();
31
35
  const start = e.node.getStart(sf);
@@ -37,7 +41,8 @@ function toDiagnostic(e) {
37
41
  line: line + 1,
38
42
  column: character + 1,
39
43
  start,
40
- length: e.node.getEnd() - start
44
+ length: e.node.getEnd() - start,
45
+ ...fix
41
46
  };
42
47
  }
43
48
  function formatDiagnostic(d) {
@@ -1407,10 +1412,17 @@ const mods$1 = (ms) => [...ms ?? []].sort((a, b) => MODIFIER_ORDER.indexOf(a) -
1407
1412
  const annotations = (as, indent) => (as ?? []).map((a) => `${indent}@${a}`);
1408
1413
  const params$3 = (ps, indent) => ps.map((p) => `${ident(p.name)}: ${printType$2(p.type)}${p.default ? ` = ${expr$2(p.default, PREC$1.lowest, indent)}` : ""}`).join(", ");
1409
1414
  function fun(f, indent) {
1410
- const tps = f.typeParams?.length ? `<${f.typeParams.map(ident).join(", ")}> ` : "";
1415
+ const bounds = (n) => f.bounds?.[n] ?? [];
1416
+ const typeParam = (n) => {
1417
+ const [only, ...more] = bounds(n);
1418
+ return only && !more.length ? `${ident(n)} : ${printType$2(only)}` : ident(n);
1419
+ };
1420
+ const where = (f.typeParams ?? []).filter((n) => bounds(n).length > 1).flatMap((n) => bounds(n).map((b) => `${ident(n)} : ${printType$2(b)}`));
1421
+ const tps = f.typeParams?.length ? `<${f.typeParams.map(typeParam).join(", ")}> ` : "";
1411
1422
  const receiver = f.receiver ? `${printType$2(f.receiver)}.` : "";
1412
1423
  const ret = f.ret ? `: ${printType$2(f.ret)}` : "";
1413
- const head = `${indent}${mods$1(f.modifiers)}fun ${tps}${receiver}${ident(f.name)}(${params$3(f.params, indent)})${ret}`;
1424
+ const clause = where.length ? ` where ${where.join(", ")}` : "";
1425
+ const head = `${indent}${mods$1(f.modifiers)}fun ${tps}${receiver}${ident(f.name)}(${params$3(f.params, indent)})${ret}${clause}`;
1414
1426
  return [...annotations(f.annotations, indent), ...f.body ? [
1415
1427
  `${head} {`,
1416
1428
  ...block$1(f.body, indent + INDENT$2),
@@ -1495,6 +1507,11 @@ const fn$4 = (params, ret) => ({
1495
1507
  params,
1496
1508
  ret
1497
1509
  });
1510
+ const blockFunction = (params, ret) => ({
1511
+ k: "blockFunction",
1512
+ params,
1513
+ ret
1514
+ });
1498
1515
  const opaque = (of) => ({
1499
1516
  k: "opaque",
1500
1517
  of
@@ -1526,6 +1543,10 @@ const arrayLiteral = (items) => ({
1526
1543
  k: "arrayLiteral",
1527
1544
  items
1528
1545
  });
1546
+ const tupleLiteral = (items) => ({
1547
+ k: "tupleLiteral",
1548
+ items
1549
+ });
1529
1550
  const dictionaryLiteral = (entries) => ({
1530
1551
  k: "dictionaryLiteral",
1531
1552
  entries
@@ -1622,10 +1643,11 @@ const INDENT$1 = " ";
1622
1643
  function printType$1(t) {
1623
1644
  switch (t.k) {
1624
1645
  case "named": return t.args?.length ? `${t.name}<${t.args.map(printType$1).join(", ")}>` : t.name;
1625
- case "optional": return t.of.k === "cFunction" || t.of.k === "function" ? `(${printType$1(t.of)})?` : `${printType$1(t.of)}?`;
1646
+ case "optional": return t.of.k === "cFunction" || t.of.k === "blockFunction" || t.of.k === "function" ? `(${printType$1(t.of)})?` : `${printType$1(t.of)}?`;
1626
1647
  case "array": return `[${printType$1(t.of)}]`;
1627
1648
  case "dictionary": return `[${printType$1(t.key)}: ${printType$1(t.value)}]`;
1628
1649
  case "cFunction": return `@convention(c) (${t.params.map(printType$1).join(", ")}) -> ${printType$1(t.ret)}`;
1650
+ case "blockFunction": return `@convention(block) (${t.params.map(printType$1).join(", ")}) -> ${printType$1(t.ret)}`;
1629
1651
  case "function": return `(${t.params.map(printType$1).join(", ")}) -> ${printType$1(t.ret)}`;
1630
1652
  case "opaque": return `some ${printType$1(t.of)}`;
1631
1653
  }
@@ -1704,6 +1726,7 @@ function bare(e, indent) {
1704
1726
  case "self": return "self";
1705
1727
  case "member": return `${expr$1(e.object, PREC.postfix, indent)}.${e.name}`;
1706
1728
  case "arrayLiteral": return `[${e.items.map((x) => expr$1(x, PREC.assign, indent)).join(", ")}]`;
1729
+ case "tupleLiteral": return `(${e.items.map((x) => expr$1(x, PREC.assign, indent)).join(", ")})`;
1707
1730
  case "dictionaryLiteral":
1708
1731
  if (!e.entries.length) return "[:]";
1709
1732
  return `[${e.entries.map((x) => `${expr$1(x.key, PREC.assign, indent)}: ${expr$1(x.value, PREC.assign, indent)}`).join(", ")}]`;
@@ -1894,7 +1917,7 @@ function bareType(t) {
1894
1917
  case "array": return `${t.readonly ? "readonly " : ""}${type$1(t.of, At.arrayElement)}[]`;
1895
1918
  case "union": return t.members.map((m) => type$1(m, At.unionMember)).join(" | ");
1896
1919
  case "intersection": return t.members.map((m) => type$1(m, At.intersectionMember)).join(" & ");
1897
- case "tuple": return `[${t.elements.map((e) => e.optional ? `${type$1(e.type, At.arrayElement)}?` : printType(e.type)).join(", ")}]`;
1920
+ case "tuple": return `[${t.elements.map((e) => e.name ? `${e.name}${e.optional ? "?" : ""}: ${printType(e.type)}` : e.optional ? `${type$1(e.type, At.arrayElement)}?` : printType(e.type)).join(", ")}]`;
1898
1921
  case "fn": return `(${params$1(t.params)}) => ${printType(t.ret)}`;
1899
1922
  case "object": return t.members.length ? `{ ${t.members.map((m) => `${m.readonly ? "readonly " : ""}${propertyName$2(m.name)}${m.optional ? "?" : ""}: ${printType(m.type)}`).join("; ")} }` : "{}";
1900
1923
  case "literal": return typeof t.value === "bigint" ? `${t.value}n` : JSON.stringify(t.value);
@@ -1962,6 +1985,14 @@ function member$2(m) {
1962
1985
  case "property": {
1963
1986
  const mods = `${m.private ? "private " : ""}${m.static ? "static " : ""}${m.readonly ? "readonly " : ""}`;
1964
1987
  const name = m.computed ? `[${m.name}]` : propertyName$2(m.name);
1988
+ if (m.set) {
1989
+ const at = `${INDENT}${m.private ? "private " : ""}${m.static ? "static " : ""}`;
1990
+ return [
1991
+ ...doc,
1992
+ `${at}get ${name}(): ${printType(m.type)};`,
1993
+ `${at}set ${name}(value: ${printType(m.set)});`
1994
+ ];
1995
+ }
1965
1996
  return [...doc, `${INDENT}${mods}${name}${m.optional ? "?" : ""}: ${printType(m.type)};`];
1966
1997
  }
1967
1998
  case "call": return [...doc, `${INDENT}${typeParams(m.typeParams)}(${params$1(m.params)}): ${printType(m.ret)};`];
@@ -2146,7 +2177,7 @@ const stmt = (s) => ({
2146
2177
  const blank = { k: "blank" };
2147
2178
  //#endregion
2148
2179
  //#region ../codegen/src/xml/index.ts
2149
- const element$1 = (name, attributes = {}, children) => children ? {
2180
+ const element$2 = (name, attributes = {}, children) => children ? {
2150
2181
  name,
2151
2182
  attributes,
2152
2183
  children
@@ -2365,7 +2396,7 @@ const PRIMS$1 = [
2365
2396
  "uint64"
2366
2397
  ];
2367
2398
  function parseSchemaType(s, module = "", typeParams = []) {
2368
- const toks = s.match(/@\w+|=>|[()[\]<>?,]|[\w.$]+/g) ?? [];
2399
+ const toks = s.match(/@\w+|=>|[()[\]<>?,:]|[\w.$]+/g) ?? [];
2369
2400
  let p = 0;
2370
2401
  const expect = (t) => {
2371
2402
  if (toks[p++] !== t) throw new Error(`schema type ${s}: expected ${t}`);
@@ -2430,6 +2461,26 @@ function parseSchemaType(s, module = "", typeParams = []) {
2430
2461
  nullable: false
2431
2462
  };
2432
2463
  }
2464
+ if (name === "Tuple") {
2465
+ const of = [];
2466
+ const labels = [];
2467
+ for (;;) {
2468
+ if (toks[p + 1] === ":") {
2469
+ labels.push(toks[p]);
2470
+ p += 2;
2471
+ }
2472
+ of.push(type());
2473
+ if (toks[p] !== ",") break;
2474
+ p++;
2475
+ }
2476
+ expect(">");
2477
+ return {
2478
+ k: "tuple",
2479
+ of,
2480
+ ...labels.length === of.length ? { labels } : {},
2481
+ nullable: false
2482
+ };
2483
+ }
2433
2484
  const args = [type()];
2434
2485
  while (toks[p] === ",") {
2435
2486
  p++;
@@ -2578,6 +2629,7 @@ function formatSchemaType(t) {
2578
2629
  }
2579
2630
  case "record": return t.cf ? `CFDictionary${q}` : `Record<${formatSchemaType(t.of)}>${q}`;
2580
2631
  case "set": return `Set<${formatSchemaType(t.of)}>${q}`;
2632
+ case "tuple": return `Tuple<${t.of.map((x, i) => `${t.labels ? `${t.labels[i]}: ` : ""}${formatSchemaType(x)}`).join(", ")}>${q}`;
2581
2633
  case "out": return `Out<${formatSchemaType(t.of)}>${q}`;
2582
2634
  case "classOf": return `Class<${t.param}>${q}`;
2583
2635
  case "tparam": return `${t.name}${q}`;
@@ -3864,13 +3916,15 @@ const CLASS_KINDS = {
3864
3916
  };
3865
3917
  function classView(k, internal, c) {
3866
3918
  const bounds = boundsOf(c.typeParameters);
3919
+ const upperBounds = upperBoundsOf(c.typeParameters, []);
3867
3920
  const view = membersView({
3868
3921
  kind: CLASS_KINDS[c.kind],
3869
3922
  ...c.data ? { data: true } : {},
3870
3923
  ...c.fun ? { fun: true } : {},
3871
3924
  ...c.modality === "sealed" ? { sealed: c.sealedSubclasses } : {},
3872
3925
  ...c.valueClass ? { value: c.valueClass } : {},
3873
- ...bounds ? { bounds } : {}
3926
+ ...bounds ? { bounds } : {},
3927
+ ...upperBounds ? { upperBounds } : {}
3874
3928
  }, [c]);
3875
3929
  for (const ctor of c.constructors) {
3876
3930
  if (ctor.jvm) view.members.set(ctor.jvm.name + ctor.jvm.descriptor, {
@@ -3902,7 +3956,8 @@ function membersView(facts, owners) {
3902
3956
  if (!f.jvm) continue;
3903
3957
  view.members.set(f.jvm.name + f.jvm.descriptor, {
3904
3958
  role: "function",
3905
- function: f
3959
+ function: f,
3960
+ outer: owner.typeParameters ?? []
3906
3961
  });
3907
3962
  if (f.parameters.some((p) => p.declaresDefault)) view.overloaded.add(f.jvm.name);
3908
3963
  }
@@ -3931,6 +3986,38 @@ function boundsOf(params) {
3931
3986
  }
3932
3987
  return Object.keys(bounds).length ? bounds : void 0;
3933
3988
  }
3989
+ function upperBoundsOf(params, outer) {
3990
+ const names = new Map([...outer, ...params].map((p) => [p.id, p.name]));
3991
+ const bounds = boundsOf(params) ?? {};
3992
+ const upper = {};
3993
+ for (const p of params) {
3994
+ if (bounds[p.name] !== "other") continue;
3995
+ const refs = p.upperBounds.map((b) => typeRef(b, names));
3996
+ if (refs.every((r) => r !== void 0)) upper[p.name] = refs;
3997
+ }
3998
+ return Object.keys(upper).length ? upper : void 0;
3999
+ }
4000
+ function typeRef(t, names) {
4001
+ const c = t.classifier;
4002
+ const name = "class" in c ? c.class.replaceAll("/", ".") : "typeAlias" in c ? c.typeAlias.replaceAll("/", ".") : names.get(c.typeParameter);
4003
+ if (!name) return void 0;
4004
+ const args = [];
4005
+ for (const a of t.arguments) {
4006
+ if (a === "*") {
4007
+ args.push("*");
4008
+ continue;
4009
+ }
4010
+ if (a.variance !== "invariant") return void 0;
4011
+ const ref = typeRef(a.type, names);
4012
+ if (!ref) return void 0;
4013
+ args.push(ref);
4014
+ }
4015
+ return {
4016
+ name,
4017
+ ...args.length ? { args } : {},
4018
+ ...t.nullable ? { nullable: true } : {}
4019
+ };
4020
+ }
3934
4021
  function kotlinSignature(member) {
3935
4022
  switch (member.role) {
3936
4023
  case "function": {
@@ -3940,6 +4027,7 @@ function kotlinSignature(member) {
3940
4027
  type: f.receiver
3941
4028
  }] : [];
3942
4029
  const bounds = boundsOf(f.typeParameters);
4030
+ const upperBounds = upperBoundsOf(f.typeParameters, member.outer);
3943
4031
  return {
3944
4032
  name: f.name,
3945
4033
  params: [
@@ -3955,7 +4043,8 @@ function kotlinSignature(member) {
3955
4043
  facts: {
3956
4044
  ...f.suspend ? { suspend: true } : {},
3957
4045
  ...f.receiver ? { extension: true } : {},
3958
- ...bounds ? { bounds } : {}
4046
+ ...bounds ? { bounds } : {},
4047
+ ...upperBounds ? { upperBounds } : {}
3959
4048
  }
3960
4049
  };
3961
4050
  }
@@ -4010,7 +4099,7 @@ function jvmSymbol(internal, member) {
4010
4099
  let extractorHash;
4011
4100
  function extractorVersion() {
4012
4101
  if (extractorHash) return extractorHash;
4013
- return extractorHash = "beb4a07a";
4102
+ return extractorHash = "ed6f33c6";
4014
4103
  }
4015
4104
  const contentHashes = /* @__PURE__ */ new Map();
4016
4105
  function contentHash(files) {
@@ -4057,7 +4146,7 @@ function jarArtifact(file) {
4057
4146
  }
4058
4147
  function iosProvenance(module, source, sdkVersion, target) {
4059
4148
  return {
4060
- artifact: source.pod ? `pod:${source.pod}` : source.kind === "sdk" ? `sdk:iphonesimulator${sdkVersion}` : `${source.kind}:${module}`,
4149
+ artifact: source.pod ? `pod:${source.pod}` : source.spm ? `spm:${source.spm}` : source.kind === "sdk" ? `sdk:iphonesimulator${sdkVersion}` : `${source.kind}:${module}`,
4061
4150
  kind: source.kind,
4062
4151
  ...source.files.length ? { contentHash: contentHash(source.files) } : {},
4063
4152
  target,
@@ -4459,11 +4548,27 @@ function extractAndroid(opts) {
4459
4548
  });
4460
4549
  throw new Unsupported$1("java.lang.Class");
4461
4550
  }
4462
- if (!known.has(t.name)) throw new Unsupported$1(t.name.replace(/\//g, "."));
4463
4551
  const typeArg = (a, i) => {
4464
4552
  const at = argument(i, t.args.length);
4465
4553
  return boxedAs(at, a) ?? typeOf(a, true, tparams, at);
4466
4554
  };
4555
+ if (kotlinFunction$1(t, kt)) {
4556
+ const last = t.args.length - 1;
4557
+ const result = argument(last, t.args.length);
4558
+ try {
4559
+ return nullable({
4560
+ k: "fn",
4561
+ params: t.args.slice(0, last).map(typeArg),
4562
+ ret: classOfKotlin(result) === "kotlin/Unit" ? parseSchemaType("void") : typeArg(t.args[last], last),
4563
+ escaping: true,
4564
+ main: false,
4565
+ nullable: false
4566
+ });
4567
+ } catch (e) {
4568
+ if (!(e instanceof Unsupported$1)) throw e;
4569
+ }
4570
+ }
4571
+ if (!known.has(t.name)) throw new Unsupported$1(t.name.replace(/\//g, "."));
4467
4572
  if (readOnlyList(t, kt)) try {
4468
4573
  return nullable({
4469
4574
  k: "array",
@@ -4693,6 +4798,9 @@ function extractAndroid(opts) {
4693
4798
  if (ks?.name && ks.name !== m.name) {
4694
4799
  method.name = ks.name;
4695
4800
  method.java = m.name;
4801
+ } else if (member && mangled(m.name)) {
4802
+ method.name = m.name.slice(0, m.name.indexOf("-"));
4803
+ method.java = m.name;
4696
4804
  }
4697
4805
  if (Object.keys(kotlinFacts).length) method.kotlin = kotlinFacts;
4698
4806
  if (m.access & ACC.STATIC) method.static = true;
@@ -4815,6 +4923,9 @@ function boxedAs(kt, t) {
4815
4923
  function readOnlyList(t, kt) {
4816
4924
  return t.name === "java/util/List" && t.args.length === 1 && !!kt && !kt.platform && classOfKotlin(kt) === "kotlin/collections/List" && typeArgument(kt, 0) !== void 0;
4817
4925
  }
4926
+ function kotlinFunction$1(t, kt) {
4927
+ return /^kotlin\/jvm\/functions\/Function\d+$/.test(t.name) && !!kt && !kt.platform && !kt.suspend && !kt.annotations?.length && classOfKotlin(kt) === `kotlin/${t.name.slice(t.name.lastIndexOf("/") + 1)}` && kt.arguments.length === t.args.length && kt.arguments.every((a) => a !== "*");
4928
+ }
4818
4929
  function typeArgument(kt, i) {
4819
4930
  const a = kt?.arguments[i];
4820
4931
  return a && a !== "*" ? a.type : void 0;
@@ -5276,18 +5387,32 @@ function parseType(frags, r) {
5276
5387
  }
5277
5388
  if (tok === "(") {
5278
5389
  const items = [];
5390
+ const labels = [];
5279
5391
  while (toks[p] !== ")") {
5392
+ const label = toks[p];
5393
+ if (typeof label === "string" && /^\w+$/.test(label) && toks[p + 1] === ":") {
5394
+ labels.push(label);
5395
+ p += 2;
5396
+ }
5280
5397
  items.push(type());
5281
5398
  if (toks[p] === ",") p++;
5282
5399
  else break;
5283
5400
  }
5284
5401
  if (toks[p++] !== ")") throw new Unsupported("closures and tuples");
5285
5402
  if (toks[p] === "->") {
5403
+ if (labels.length) throw new Unsupported("closures with labeled parameters");
5286
5404
  p++;
5287
5405
  return closure(items, attrs);
5288
5406
  }
5289
- if (items.length === 1 && !attrs.length) return items[0];
5290
- throw new Unsupported("tuples");
5407
+ if (items.length === 1 && !attrs.length && !labels.length) return items[0];
5408
+ if (!items.length && !attrs.length) return parseSchemaType("void");
5409
+ if (attrs.length) throw new Unsupported(`type syntax ${attrs.join(" ")}`);
5410
+ return {
5411
+ k: "tuple",
5412
+ of: items,
5413
+ ...labels.length === items.length ? { labels } : {},
5414
+ nullable: false
5415
+ };
5291
5416
  }
5292
5417
  if (tok === "->") throw new Unsupported("closures and tuples");
5293
5418
  if (attrs.length) throw new Unsupported(`type syntax ${attrs.join(" ")}`);
@@ -5621,6 +5746,7 @@ function undeclaredType(t, declared) {
5621
5746
  case "record":
5622
5747
  case "out": return undeclaredType(t.of, declared);
5623
5748
  case "fn": return [...t.params, t.ret].map((x) => undeclaredType(x, declared)).find(Boolean);
5749
+ case "tuple": return t.of.map((x) => undeclaredType(x, declared)).find(Boolean);
5624
5750
  default: return;
5625
5751
  }
5626
5752
  }
@@ -5666,8 +5792,8 @@ const NOT_JAVA = /* @__PURE__ */ new Set([
5666
5792
  "id",
5667
5793
  "record",
5668
5794
  "set",
5795
+ "tuple",
5669
5796
  "out",
5670
- "fn",
5671
5797
  "error"
5672
5798
  ]);
5673
5799
  const SWIFT_SCALARS = {
@@ -5932,26 +6058,19 @@ function needsKotlinShim(member) {
5932
6058
  return !!k?.suspend || !!k?.unboxed || "params" in member && member.params.some((p) => p.kotlin?.suspendFunction);
5933
6059
  }
5934
6060
  function bounded$1(owner, member) {
5935
- const other = (bounds) => !!bounds && Object.values(bounds).includes("other");
5936
- return other(owner?.kotlin?.bounds) || other(member.kotlin?.bounds);
6061
+ const unwritable = (facts) => Object.entries(facts?.bounds ?? {}).some(([name, bound]) => bound === "other" && !facts?.upperBounds?.[name]);
6062
+ return unwritable(owner?.kotlin) || unwritable(member.kotlin);
5937
6063
  }
5938
6064
  function omitsKotlinDefault(owner, member, param) {
5939
6065
  return !!param.kotlin?.default && !bounded$1(owner, member);
5940
6066
  }
5941
- const KOTLIN_SHIM_REFUSALS = [
5942
- [(owner, member) => bounded$1(owner, member), {
5943
- rule: "kotlin-shim-generic",
5944
- reason: "generic Kotlin members whose type parameters have bounds are not supported through a shim yet"
5945
- }],
5946
- [(_, __, role) => role === "set", {
5947
- rule: "kotlin-shim",
5948
- reason: "assigning Kotlin value classes is not supported yet"
5949
- }],
5950
- [(_, __, role) => role === "implement", {
5951
- rule: "kotlin-shim",
5952
- reason: "Lucent classes cannot implement suspend functions or value-class members yet"
5953
- }]
5954
- ];
6067
+ const KOTLIN_SHIM_REFUSALS = [[(owner, member) => bounded$1(owner, member), {
6068
+ rule: "kotlin-shim-generic",
6069
+ reason: "generic Kotlin members bounded by a projected type (`T : List<out R>`) are not supported through a shim yet"
6070
+ }], [(owner, _, role) => role === "implement" && !owner?.interface, {
6071
+ rule: "kotlin-shim",
6072
+ reason: "Lucent classes cannot override a Kotlin class's suspend or value-class members yet"
6073
+ }]];
5955
6074
  const UI_APPLIER$1 = "androidx.compose.ui.UiComposable";
5956
6075
  const simpleName = (kotlinName) => kotlinName.slice(kotlinName.lastIndexOf("/") + 1);
5957
6076
  const KOTLIN_SOURCE_REFUSALS = [
@@ -6011,9 +6130,9 @@ function refusalOf(owner, member, backend, role) {
6011
6130
  };
6012
6131
  }
6013
6132
  const jvmName = "java" in member ? member.java : void 0;
6014
- if (backend === "jni" && role === "implement" && jvmName && !javaIdentifier(jvmName)) return {
6133
+ if (backend === "jni" && role === "implement" && !owner?.interface && jvmName && !javaIdentifier(jvmName)) return {
6015
6134
  rule: "jvm-mangled-name",
6016
- reason: `a method whose JVM name Java cannot write (${jvmName}) cannot be implemented`
6135
+ reason: `a method whose JVM name Java cannot write (${jvmName}) cannot be overridden`
6017
6136
  };
6018
6137
  if (backend !== "swift-shim") return void 0;
6019
6138
  if (role === "new" && member.swift?.async) return {
@@ -6051,9 +6170,12 @@ function requirementDelivery(backend, owner, m) {
6051
6170
  return !isVoid || owner?.mainActor || m.mainActor ? "sync" : "queued";
6052
6171
  }
6053
6172
  function resultOwnership(owner, member, module, role, facts) {
6054
- if (module.platform !== "ios" || member.swift || role !== "call" || !("returns" in member)) return facts;
6173
+ const cFunction = "cFunction" in member ? member.cFunction?.name : void 0;
6174
+ const made = role === "new" && !!cFunction;
6175
+ if (module.platform !== "ios" || member.swift) return facts;
6176
+ if (!made && (role !== "call" || !("returns" in member))) return facts;
6055
6177
  if (facts.ownership !== "unknown") return facts;
6056
- const rule = owner ? /^(alloc|new|copy|mutableCopy|create)(?![a-z])/.test(member.selector ?? member.name) ? "objc-method-family" : void 0 : /Create|Copy/.test(member.name) ? "cf-create-rule" : void 0;
6178
+ const rule = cFunction ? /Create|Copy/.test(cFunction) ? "cf-create-rule" : void 0 : owner ? /^(alloc|new|copy|mutableCopy|create)(?![a-z])/.test(member.selector ?? ("name" in member ? member.name : "")) ? "objc-method-family" : void 0 : /Create|Copy/.test("name" in member ? member.name : "") ? "cf-create-rule" : void 0;
6057
6179
  if (!rule) return facts;
6058
6180
  const evidence = {
6059
6181
  fact: "ownership",
@@ -6141,6 +6263,11 @@ function kindConversion(t, place, ctx) {
6141
6263
  type: t,
6142
6264
  of: [inner(t.of, { element: true })]
6143
6265
  };
6266
+ case "tuple": return {
6267
+ op: "copy-tuple",
6268
+ type: t,
6269
+ of: t.of.map((x) => inner(x, { element: true }))
6270
+ };
6144
6271
  case "record": return withDetail({
6145
6272
  op: "copy-record",
6146
6273
  type: t,
@@ -6255,9 +6382,15 @@ function kotlinSourceRule(t, place) {
6255
6382
  }
6256
6383
  function jniRule(t, place, ctx) {
6257
6384
  if (t.k === "array" && !t.list && t.of.k === "tparam" && place.flow === "in") return "arrays of a type parameter's values cannot be passed to Java yet";
6385
+ if (ctx.backend === "jni" && t.k === "fn" && [...t.params, t.ret].some((x) => x.k === "fn")) return "Kotlin functions taking or giving functions are not supported yet";
6258
6386
  if (ctx.role !== "implement") return void 0;
6259
6387
  if (place.offered && t.k === "prim" && t.name === "char") return "a char argument is not supported yet";
6260
- if (place.result && t.k !== "prim" && t.k !== "string" && t.k !== "tparam") return `Lucent functions cannot return a ${formatSchemaType({
6388
+ if (place.result && ![
6389
+ "prim",
6390
+ "string",
6391
+ "tparam",
6392
+ "ref"
6393
+ ].includes(t.k)) return `Lucent functions cannot return a ${formatSchemaType({
6261
6394
  ...t,
6262
6395
  nullable: false
6263
6396
  })} to Java yet`;
@@ -6299,6 +6432,21 @@ function swiftRule(t, place, ctx) {
6299
6432
  case "date":
6300
6433
  case "id":
6301
6434
  case "tparam": return;
6435
+ case "fn": {
6436
+ const blockable = (x, result) => {
6437
+ if (x.k === "prim") return result && x.name === "void" || !!SWIFT_SCALARS[x.name] && !x.nullable;
6438
+ if (x.k === "string") return true;
6439
+ if (x.k !== "ref") return false;
6440
+ const facts = ctx.types(x.module, x.name);
6441
+ return (facts?.kind === "class" || facts?.kind === "protocol") && !facts.swift;
6442
+ };
6443
+ if (![...t.params.map((x) => blockable(x, false)), blockable(t.ret, true)].every(Boolean)) return not("closures taking or giving values other than numbers, booleans, strings and Objective-C objects");
6444
+ return t.nullable ? not("optional closures") : void 0;
6445
+ }
6446
+ case "tuple":
6447
+ if (t.of.some((x) => x.nullable)) return not("tuples of optional values");
6448
+ if (t.of.some((x) => isStruct(x, ctx))) return not("tuples of C structs");
6449
+ return t.nullable ? not("optional tuples") : void 0;
6302
6450
  case "array":
6303
6451
  case "record":
6304
6452
  if (t.of.nullable) return not("collections of optional values");
@@ -6351,6 +6499,51 @@ function hasUnion$1(t, ctx) {
6351
6499
  return swift !== void 0 && swift !== true && !!swift.cases;
6352
6500
  }
6353
6501
  //#endregion
6502
+ //#region ../bindgen/src/c-swift-names.ts
6503
+ function cSwiftNames(dirs) {
6504
+ const out = /* @__PURE__ */ new Map();
6505
+ for (const dir of dirs) {
6506
+ const files = fs.existsSync(dir) ? fs.readdirSync(dir) : [];
6507
+ for (const f of files.filter((x) => x.endsWith(".h"))) for (const [name, swift] of attributeNames(fs.readFileSync(path.join(dir, f), "utf8"))) out.set(name, swift);
6508
+ for (const f of files.filter((x) => x.endsWith(".apinotes"))) for (const [name, swift] of apiNoteNames(fs.readFileSync(path.join(dir, f), "utf8"))) out.set(name, swift);
6509
+ }
6510
+ return out;
6511
+ }
6512
+ function apiNoteNames(text) {
6513
+ const out = [];
6514
+ const items = text.split(/^\s*- (?=Name:)/m).slice(1);
6515
+ for (const item of items) {
6516
+ const name = /^Name:\s*(\w+)/.exec(item)?.[1];
6517
+ const own = item.split(/\n(?=\S|\s*- )/)[0];
6518
+ const swift = /^\s*SwiftName:\s*'?([^'\n]+?)'?\s*$/m.exec(own)?.[1];
6519
+ if (name && swift) out.push([name, swift]);
6520
+ }
6521
+ return out;
6522
+ }
6523
+ function attributeNames(text) {
6524
+ const out = [];
6525
+ for (const m of text.matchAll(/\b(?:CF|NS|CG)_SWIFT_NAME\(([^()]*\([^()]*\))\)|swift_name\("([^"]+)"\)/g)) {
6526
+ const swift = m[1] ?? m[2];
6527
+ const before = text.slice(0, m.index);
6528
+ const start = Math.max(before.lastIndexOf(";"), before.lastIndexOf("}")) + 1;
6529
+ const name = /\b(\w+)\s*\(/.exec(before.slice(start))?.[1];
6530
+ if (name) out.push([name, swift]);
6531
+ }
6532
+ return out;
6533
+ }
6534
+ function swiftMemberOf(swift) {
6535
+ const m = /^(?:(getter|setter):)?([\w.]+)\.(\w+)\(([^)]*)\)$/.exec(swift);
6536
+ if (!m) return void 0;
6537
+ const [, accessor, type, name, args] = m;
6538
+ const self = args.split(":").filter((l) => l !== "").indexOf("self");
6539
+ return {
6540
+ kind: accessor === "getter" || accessor === "setter" ? accessor : name === "init" ? "init" : "method",
6541
+ type,
6542
+ name,
6543
+ ...self >= 0 ? { self } : {}
6544
+ };
6545
+ }
6546
+ //#endregion
6354
6547
  //#region ../bindgen/src/swift.ts
6355
6548
  const TYPE_KINDS$1 = {
6356
6549
  "swift.struct": "struct",
@@ -6562,7 +6755,9 @@ function addSwiftDeclarations(ctx) {
6562
6755
  bytes: true
6563
6756
  }
6564
6757
  });
6565
- if (bound.ctors.length) cls.constructors = bound.ctors;
6758
+ const apart = factoriesOfSameTyped(bound.ctors, `${module}.${cls.name}`);
6759
+ bound.methods.push(...apart.factories);
6760
+ if (apart.ctors.length) cls.constructors = apart.ctors;
6566
6761
  if (bound.methods.length) cls.methods = bound.methods;
6567
6762
  if (bound.props.length) cls.properties = bound.props;
6568
6763
  mod.types.push(cls);
@@ -6580,7 +6775,11 @@ function addSwiftDeclarations(ctx) {
6580
6775
  const methods = withoutPropertyNames(bound.methods, cls.properties ?? [], bound.symbols, skip);
6581
6776
  for (const m of methods) if (!has(cls.methods, m.name)) (cls.methods ??= []).push(m);
6582
6777
  for (const p of bound.props) if (!has(cls.properties, p.name)) (cls.properties ??= []).push(p);
6583
- if (bound.ctors.length && !cls.constructors?.length) cls.constructors = bound.ctors;
6778
+ if (bound.ctors.length && !cls.constructors?.length) {
6779
+ const apart = factoriesOfSameTyped(bound.ctors, `${module}.${cls.name}`);
6780
+ for (const f of apart.factories) if (!has(cls.methods, f.name)) (cls.methods ??= []).push(f);
6781
+ if (apart.ctors.length) cls.constructors = apart.ctors;
6782
+ }
6584
6783
  }
6585
6784
  for (const s of g.symbols) {
6586
6785
  const usr = s.identifier.precise;
@@ -6862,6 +7061,44 @@ function payload(c, r) {
6862
7061
  } : { type };
6863
7062
  });
6864
7063
  }
7064
+ function factoriesOfSameTyped(ctors, self) {
7065
+ const key = (c) => c.params.map((p) => typeKind(formatSchemaType({
7066
+ ...p.type,
7067
+ nullable: false
7068
+ }))).join(",");
7069
+ const groups = /* @__PURE__ */ new Map();
7070
+ for (const c of ctors) groups.set(key(c), [...groups.get(key(c)) ?? [], c]);
7071
+ const capitalized = (w) => w.charAt(0).toUpperCase() + w.slice(1);
7072
+ const byLabels = (c) => `with${splitName(c.swift?.name ?? "init()").labels.filter((l) => l !== "_").map(capitalized).join("")}`;
7073
+ const unlabeled = (c) => splitName(c.swift?.name ?? "init()").labels.every((l) => l === "_");
7074
+ const byTypes = (c) => `with${c.params.map((p) => capitalized(formatSchemaType(p.type).replace(/\W/g, ""))).join("")}`;
7075
+ const factories = [];
7076
+ const turned = /* @__PURE__ */ new Set();
7077
+ for (const all of groups.values()) {
7078
+ if (all.length < 2) continue;
7079
+ const bare = all.filter((c) => !c.params.length || unlabeled(c));
7080
+ const group = bare.length === 1 ? all.filter((c) => c !== bare[0]) : all;
7081
+ const labelled = group.map(byLabels);
7082
+ const names = new Set(labelled).size === group.length ? labelled : group.map(byTypes);
7083
+ if (new Set(names).size !== group.length) continue;
7084
+ group.forEach((c, i) => {
7085
+ factories.push({
7086
+ ...c,
7087
+ name: names[i],
7088
+ static: true,
7089
+ returns: parseSchemaType(self)
7090
+ });
7091
+ turned.add(c);
7092
+ });
7093
+ }
7094
+ return {
7095
+ ctors: ctors.filter((c) => !turned.has(c)),
7096
+ factories
7097
+ };
7098
+ }
7099
+ function typeKind(t) {
7100
+ return /^(double|float|CGFloat|NSInteger|NSUInteger|u?int(8|16|32|64)?|short|byte)$/.test(t) ? "number" : t;
7101
+ }
6865
7102
  //#endregion
6866
7103
  //#region ../bindgen/src/ios.ts
6867
7104
  const DEFAULT_TARGET = "arm64-apple-ios15.1-simulator";
@@ -7142,6 +7379,26 @@ function externalUsrs(g) {
7142
7379
  for (const r of g.relationships) if (r.target.startsWith("c:") && !declared.has(r.target)) out.add(r.target);
7143
7380
  return out;
7144
7381
  }
7382
+ function withInheritedInitializers(mod) {
7383
+ const classes = new Map(mod.types.filter((t) => t.kind === "class").map((c) => [c.name, c]));
7384
+ for (const cls of classes.values()) {
7385
+ if (!cls.inheritsInit || !cls.constructors?.length) continue;
7386
+ let inherited;
7387
+ for (let at = cls.extends, depth = 0; at && depth < 64 && !inherited; depth++) {
7388
+ const [owner, ...rest] = at.split(".");
7389
+ const sup = owner === mod.module ? classes.get(rest.join(".")) : void 0;
7390
+ if (!sup) break;
7391
+ const own = (sup.constructors ?? []).filter((c) => !c.factory);
7392
+ if (own.length) inherited = own;
7393
+ else if (!sup.inheritsInit) break;
7394
+ at = sup.extends;
7395
+ }
7396
+ if (inherited) {
7397
+ cls.constructors.push(...inherited.map((c) => ({ ...c })));
7398
+ delete cls.inheritsInit;
7399
+ }
7400
+ }
7401
+ }
7145
7402
  function keepInheritedNonNull(mod, unaudited) {
7146
7403
  const classes = new Map(mod.types.filter((t) => t.kind === "class").map((c) => [c.name, c]));
7147
7404
  const inheritedNonNull = (cls, p) => {
@@ -7293,7 +7550,7 @@ function inheritedConformances(classUsr, lineage) {
7293
7550
  }
7294
7551
  return out;
7295
7552
  }
7296
- function buildIosSchema(module, g, names, values) {
7553
+ function buildIosSchema(module, g, names, values, importedNames = /* @__PURE__ */ new Map()) {
7297
7554
  const refs = new Map(names.flatMap((n) => Object.entries(n.refs)));
7298
7555
  const aliases = new Map(names.flatMap((n) => Object.entries(n.aliases)));
7299
7556
  const unaudited = /* @__PURE__ */ new Set();
@@ -7401,15 +7658,90 @@ function buildIosSchema(module, g, names, values) {
7401
7658
  properties: props
7402
7659
  });
7403
7660
  }
7661
+ const cfMembers = (cls, list, setters) => {
7662
+ const r = resolver();
7663
+ for (const mem of list) {
7664
+ const fn = /^c:@F@(\w+)$/.exec(mem.identifier.precise)?.[1];
7665
+ if (!fn || unavailable(mem)) continue;
7666
+ const imported = importedNames.get(fn);
7667
+ const member = imported ? swiftMemberOf(imported) : void 0;
7668
+ const symbol = graphSymbol(mem.identifier.precise);
7669
+ const v = since(mem);
7670
+ try {
7671
+ if (!member) throw new Unsupported(`${fn}'s Swift name is in no API notes or header Lucent reads`);
7672
+ const k = mem.kind.identifier;
7673
+ if (k === "swift.property" || k === "swift.type.property") {
7674
+ if (member.kind !== "getter") continue;
7675
+ const setter = setters.get(`${member.type}.${member.name}`);
7676
+ const p = {
7677
+ name: mem.names.title,
7678
+ type: parseType(propertyType(mem.declarationFragments ?? []), r),
7679
+ cFunctions: {
7680
+ getter: fn,
7681
+ ...setter ? { setter } : {}
7682
+ },
7683
+ symbol
7684
+ };
7685
+ if (!setter) p.readonly = true;
7686
+ if (member.self === void 0) p.static = true;
7687
+ if (v && v !== cls.since) p.since = v;
7688
+ (cls.properties ??= []).push(p);
7689
+ continue;
7690
+ }
7691
+ const sig = mem.functionSignature;
7692
+ const params = (sig?.parameters ?? []).map((pp) => ({
7693
+ name: pp.internalName ?? pp.name,
7694
+ type: parseType(afterColon(pp.declarationFragments), r)
7695
+ }));
7696
+ if (k === "swift.init") {
7697
+ if (/\binit\?/.test(declText(mem))) throw new Unsupported("a failable initializer");
7698
+ const c = {
7699
+ params,
7700
+ cFunction: { name: fn },
7701
+ symbol
7702
+ };
7703
+ if (v && v !== cls.since) c.since = v;
7704
+ (cls.constructors ??= []).push(c);
7705
+ continue;
7706
+ }
7707
+ if (k !== "swift.method" && k !== "swift.type.method") continue;
7708
+ const m = {
7709
+ name: splitName(mem.names.title).base,
7710
+ params,
7711
+ returns: sig?.returns?.length ? parseType(sig.returns, r) : parseSchemaType("void"),
7712
+ cFunction: {
7713
+ name: fn,
7714
+ ...member.self !== void 0 ? { self: member.self } : {}
7715
+ },
7716
+ symbol
7717
+ };
7718
+ if (member.self === void 0) m.static = true;
7719
+ if (v && v !== cls.since) m.since = v;
7720
+ (cls.methods ??= []).push(m);
7721
+ } catch (e) {
7722
+ if (e instanceof Unsupported) skip(cls.name, mem, e.message);
7723
+ else throw e;
7724
+ }
7725
+ }
7726
+ if (cls.methods) disambiguate(cls.methods);
7727
+ };
7728
+ const setters = /* @__PURE__ */ new Map();
7729
+ for (const [fn, imported] of importedNames) {
7730
+ const member = swiftMemberOf(imported);
7731
+ if (member?.kind === "setter") setters.set(`${member.type}.${member.name}`, fn);
7732
+ }
7404
7733
  for (const s of g.symbols) {
7405
7734
  const handle = s.kind.identifier === "swift.class" ? typedefName(s.identifier.precise) : void 0;
7406
- if (handle && !unavailable(s)) mod.types.push({
7735
+ if (!handle || unavailable(s)) continue;
7736
+ const cls = {
7407
7737
  kind: "class",
7408
7738
  name: s.pathComponents.join("_"),
7409
7739
  native: handle,
7410
7740
  cf: true,
7411
7741
  symbol: graphSymbol(s.identifier.precise)
7412
- });
7742
+ };
7743
+ cfMembers(cls, members.get(s.identifier.precise) ?? [], setters);
7744
+ mod.types.push(cls);
7413
7745
  }
7414
7746
  const objcClasses = /* @__PURE__ */ new Map();
7415
7747
  for (const s of g.symbols) {
@@ -7492,10 +7824,10 @@ function buildIosSchema(module, g, names, values) {
7492
7824
  type: withEscaping(parseType(afterColon(pp.declarationFragments), r), escaping[i])
7493
7825
  }));
7494
7826
  if (mem.kind.identifier === "swift.init") {
7495
- if (kind === "cm") continue;
7496
7827
  const c = {
7497
7828
  params,
7498
7829
  selector,
7830
+ ...kind === "cm" ? { factory: true } : {},
7499
7831
  symbol
7500
7832
  };
7501
7833
  if (facts) c.facts = facts;
@@ -7520,7 +7852,9 @@ function buildIosSchema(module, g, names, values) {
7520
7852
  const twin = asyncTwins.get(mem.identifier.precise);
7521
7853
  if (twin) try {
7522
7854
  const tr = twin.functionSignature?.returns;
7523
- method.async = { returns: tr?.length ? parseType(tr, r) : parseSchemaType("void") };
7855
+ const settled = tr?.length ? parseType(tr, r) : parseSchemaType("void");
7856
+ if (settled.k === "tuple") throw new Unsupported("tuples");
7857
+ method.async = { returns: settled };
7524
7858
  if (/\bthrows\b/.test(declText(twin))) method.async.throws = true;
7525
7859
  const asyncName = splitName(twin.names.title).base;
7526
7860
  if (asyncName !== base) method.async.name = asyncName;
@@ -7551,7 +7885,7 @@ function buildIosSchema(module, g, names, values) {
7551
7885
  if (swiftName) swiftNames.set(x, swiftName);
7552
7886
  delete x.swiftName;
7553
7887
  }
7554
- if (!ctors.length && !initUnavailable && k === "swift.class") {
7888
+ if (!ctors.some((c) => !c.factory) && !initUnavailable && k === "swift.class") {
7555
7889
  if (cls.extends) cls.inheritsInit = true;
7556
7890
  else ctors.push({
7557
7891
  params: [],
@@ -7621,6 +7955,7 @@ function buildIosSchema(module, g, names, values) {
7621
7955
  return !!t && (t.typeParams ?? 0) === arity;
7622
7956
  });
7623
7957
  keepInheritedNonNull(mod, unaudited);
7958
+ withInheritedInitializers(mod);
7624
7959
  resolveMemberKinds(mod, names);
7625
7960
  return mod;
7626
7961
  }
@@ -7863,7 +8198,7 @@ function iosArtifacts(memo, inputs) {
7863
8198
  }];
7864
8199
  const groups = /* @__PURE__ */ new Map();
7865
8200
  for (const [module, source] of sources) {
7866
- const id = source.pod ? `pod:${source.pod}` : `${source.kind}:${module}`;
8201
+ const id = source.pod ? `pod:${source.pod}` : source.spm ? `spm:${source.spm}` : `${source.kind}:${module}`;
7867
8202
  const group = groups.get(id) ?? {
7868
8203
  source,
7869
8204
  modules: []
@@ -7887,6 +8222,10 @@ function iosArtifacts(memo, inputs) {
7887
8222
  package: name,
7888
8223
  version: pod.version,
7889
8224
  buildFile: inputs.lockfile
8225
+ } : source.spm ? {
8226
+ package: source.spm.slice(0, source.spm.lastIndexOf("@")),
8227
+ version: source.spm.slice(source.spm.lastIndexOf("@") + 1),
8228
+ buildFile: inputs.resolved ?? files[0] ?? ""
7890
8229
  } : {
7891
8230
  package: modules[0],
7892
8231
  version: "",
@@ -8413,13 +8752,14 @@ function extractionCount() {
8413
8752
  return extractions;
8414
8753
  }
8415
8754
  const loaded$1 = /* @__PURE__ */ new Map();
8416
- const located$3 = /* @__PURE__ */ new Map();
8755
+ const iosSdks = /* @__PURE__ */ new Map();
8417
8756
  const headerIndexes = /* @__PURE__ */ new Map();
8418
8757
  function forgetLoadedSdks() {
8419
8758
  loaded$1.clear();
8420
- located$3.clear();
8759
+ iosSdks.clear();
8421
8760
  headerIndexes.clear();
8422
8761
  locatedByObject = /* @__PURE__ */ new WeakMap();
8762
+ namesRead = /* @__PURE__ */ new WeakMap();
8423
8763
  }
8424
8764
  const extractorKey = () => [extractorVersion(), `schema format 1`];
8425
8765
  const memoDir = (root) => path.join(root, "memo", extractorVersion());
@@ -8580,26 +8920,29 @@ function podOf(files, podsDir, pods) {
8580
8920
  }
8581
8921
  function locateIos(opts) {
8582
8922
  const xcrun = opts.ios?.xcrun ?? process.env.LUCENT_XCRUN ?? "xcrun";
8583
- const sdk = run(xcrun, [
8584
- "--sdk",
8585
- "iphonesimulator",
8586
- "--show-sdk-path"
8587
- ]);
8588
- const version = run(xcrun, [
8589
- "--sdk",
8590
- "iphonesimulator",
8591
- "--show-sdk-version"
8592
- ]);
8593
- const build = run(xcrun, [
8594
- "--sdk",
8595
- "iphonesimulator",
8596
- "--show-sdk-build-version"
8597
- ]);
8923
+ let answers = iosSdks.get(xcrun);
8924
+ if (!answers) {
8925
+ answers = [
8926
+ "--show-sdk-path",
8927
+ "--show-sdk-version",
8928
+ "--show-sdk-build-version"
8929
+ ].map((q) => run(xcrun, [
8930
+ "--sdk",
8931
+ "iphonesimulator",
8932
+ q
8933
+ ]));
8934
+ iosSdks.set(xcrun, answers);
8935
+ }
8936
+ const [sdk, version, build] = answers;
8598
8937
  if (!sdk || !version || !build) return { missing: `the iOS SDK was not found (${xcrun} --sdk iphonesimulator failed). Install Xcode and select it: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer` };
8599
8938
  const includePaths = opts.ios?.includePaths ?? [];
8600
8939
  const root = cacheRoot(opts.cacheDir);
8601
8940
  const memo = memoDir(root);
8602
- const frameworkPaths = [...opts.ios?.frameworkPaths ?? [], ...(opts.ios?.frameworks ?? []).map((f) => podFramework(memo, f))];
8941
+ const frameworkPaths = [
8942
+ ...opts.ios?.frameworkPaths ?? [],
8943
+ ...(opts.ios?.frameworks ?? []).map((f) => podFramework(memo, f)),
8944
+ ...new Set((opts.ios?.swiftPackages?.modules ?? []).filter((m) => m.framework).map((m) => m.dir))
8945
+ ];
8603
8946
  const moduleMaps = opts.ios?.moduleMaps ?? [];
8604
8947
  const defines = opts.ios?.defines ?? [];
8605
8948
  const frameworks = path.join(sdk, "System/Library/Frameworks");
@@ -8636,6 +8979,17 @@ function locateIos(opts) {
8636
8979
  }
8637
8980
  }
8638
8981
  for (const map of moduleMaps) readMap(map);
8982
+ const packages = opts.ios?.swiftPackages;
8983
+ for (const m of packages?.modules ?? []) {
8984
+ if (m.framework) continue;
8985
+ modules.set(m.module, []);
8986
+ sources.set(m.module, {
8987
+ kind: "swift-module",
8988
+ files: [path.join(m.dir, `${m.module}.swiftmodule`)],
8989
+ spm: m.package
8990
+ });
8991
+ }
8992
+ const packageDirs = [...new Set((packages?.modules ?? []).filter((m) => !m.framework).map((m) => m.dir))];
8639
8993
  for (const dir of frameworkPaths) for (const f of fs.existsSync(dir) ? fs.readdirSync(dir) : []) {
8640
8994
  if (!f.endsWith(".framework")) continue;
8641
8995
  const name = f.slice(0, -10);
@@ -8647,6 +9001,10 @@ function locateIos(opts) {
8647
9001
  });
8648
9002
  frameworkDirs.set(name, dir);
8649
9003
  }
9004
+ for (const m of packages?.modules ?? []) {
9005
+ const source = m.framework ? sources.get(m.module) : void 0;
9006
+ if (source) source.spm = m.package;
9007
+ }
8650
9008
  for (const f of opts.ios?.frameworks ?? []) sources.set(f.module, {
8651
9009
  kind: "framework",
8652
9010
  files: [
@@ -8664,13 +9022,15 @@ function locateIos(opts) {
8664
9022
  if (pod) source.pod = `${pod}@${pods.get(pod).version}`;
8665
9023
  }
8666
9024
  }
9025
+ const deployment = opts.ios?.deploymentTarget;
8667
9026
  const ios = {
8668
9027
  modules: [],
8669
- includePaths,
9028
+ includePaths: [...includePaths, ...packageDirs],
8670
9029
  frameworkPaths,
8671
9030
  moduleMaps,
8672
9031
  defines,
8673
- xcrun
9032
+ xcrun,
9033
+ ...deployment ? { target: `arm64-apple-ios${deployment}-simulator` } : {}
8674
9034
  };
8675
9035
  const targetTriple = iosTarget(ios);
8676
9036
  const artifacts = iosArtifacts(memo, {
@@ -8683,7 +9043,8 @@ function locateIos(opts) {
8683
9043
  sources,
8684
9044
  lockfile,
8685
9045
  pods,
8686
- includePaths,
9046
+ ...packages?.resolved ? { resolved: packages.resolved } : {},
9047
+ includePaths: ios.includePaths ?? [],
8687
9048
  compilerArguments: defines.map((d) => `-D${d}`),
8688
9049
  targetTriple
8689
9050
  });
@@ -8705,7 +9066,8 @@ function locateIos(opts) {
8705
9066
  modules,
8706
9067
  umbrellas,
8707
9068
  frameworkDirs,
8708
- sources
9069
+ sources,
9070
+ packageFailures: packages?.failures ?? []
8709
9071
  }
8710
9072
  }, (a) => a.modules.filter((m) => byModule.get(m) === a));
8711
9073
  }
@@ -8795,8 +9157,15 @@ function graphs(r, modules) {
8795
9157
  });
8796
9158
  return out;
8797
9159
  }
9160
+ let namesRead = /* @__PURE__ */ new WeakMap();
8798
9161
  function namesFor(r, modules) {
8799
- const read = (m) => findEntry(r, path.join(r.scope, m), "names")?.names;
9162
+ const known = namesRead.get(r) ?? /* @__PURE__ */ new Map();
9163
+ namesRead.set(r, known);
9164
+ const read = (m) => {
9165
+ const names = known.get(m) ?? findEntry(r, path.join(r.scope, m), "names")?.names;
9166
+ if (names) known.set(m, names);
9167
+ return names;
9168
+ };
8800
9169
  const missing = modules.filter((m) => !read(m));
8801
9170
  for (const [m, g] of graphs(r, missing)) publishEntry(path.join(r.scope, m), "names", {
8802
9171
  inputs: inputsOf(r, [m]),
@@ -8811,7 +9180,10 @@ function iosNotFound(r, module) {
8811
9180
  ios.moduleMaps?.length ? `${ios.moduleMaps.length} module map${ios.moduleMaps.length === 1 ? "" : "s"}` : "",
8812
9181
  ios.frameworkPaths?.length ? `${ios.frameworkPaths.length} framework path${ios.frameworkPaths.length === 1 ? "" : "s"}` : ""
8813
9182
  ].filter(Boolean);
8814
- return { missing: `lucent:ios/${module} was not found in the SDK or the app's dependencies (${`looked in ${r.ios.frameworks}${extra.length ? ` and the app's pods (${extra.join(", ")}); run pod install after adding a pod` : ""}`})` };
9183
+ const pods = extra.length ? ` and the app's pods (${extra.join(", ")}); run pod install after adding a pod` : "; no pods were read: when it comes from a pod, run pod install first";
9184
+ const where = `looked in ${r.ios.frameworks}${pods}`;
9185
+ const failed = r.ios.packageFailures;
9186
+ return { missing: `lucent:ios/${module} was not found in the SDK or the app's dependencies (${where})${failed.length ? `; the app's Swift packages could not all be built: ${failed.join("; ")}` : ""}` };
8815
9187
  }
8816
9188
  function extractIosModule(r, module) {
8817
9189
  const { modules, sdk: sdkPath, ios } = r.ios;
@@ -8828,7 +9200,7 @@ function extractIosModule(r, module) {
8828
9200
  referenced.delete(module);
8829
9201
  const names = [own, ...namesFor(r, [...referenced].filter((m) => modules.has(m)))];
8830
9202
  const headers = modules.get(module) ?? [`${module}/${module}.h`];
8831
- const schema = buildIosSchema(module, g, names, (enums) => enumValues(enums, headers, ios, sdkPath));
9203
+ const schema = buildIosSchema(module, g, names, (enums) => enumValues(enums, headers, ios, sdkPath), cSwiftNames(modules.get(module) ? [...new Set(headers.map((h) => path.dirname(h)))] : [path.join(r.ios.frameworkDirs.get(module) ?? r.ios.frameworks, `${module}.framework/Headers`)]));
8832
9204
  const umbrella = r.ios.umbrellas.get(module);
8833
9205
  const framework = r.ios.frameworkDirs.get(module) ?? (modules.get(module) ? void 0 : r.ios.frameworks);
8834
9206
  const inFramework = framework && frameworkUmbrella(framework, module);
@@ -8919,19 +9291,10 @@ let locatedByObject = /* @__PURE__ */ new WeakMap();
8919
9291
  function locate$1(platform, opts) {
8920
9292
  const byObject = locatedByObject.get(opts)?.get(platform);
8921
9293
  if (byObject) return byObject;
8922
- const found = locateByValue(platform, opts);
9294
+ const found = platform === "android" ? locateAndroid(opts) : locateIos(opts);
8923
9295
  locatedByObject.set(opts, (locatedByObject.get(opts) ?? /* @__PURE__ */ new Map()).set(platform, found));
8924
9296
  return found;
8925
9297
  }
8926
- function locateByValue(platform, opts) {
8927
- const k = `${platform}|${JSON.stringify(opts)}`;
8928
- let l = located$3.get(k);
8929
- if (!l) {
8930
- l = platform === "android" ? locateAndroid(opts) : locateIos(opts);
8931
- located$3.set(k, l);
8932
- }
8933
- return l;
8934
- }
8935
9298
  function load$1(platform, r, module) {
8936
9299
  if (!r.providers.has(module)) return { lookup: platform === "android" ? androidNotFound(r, module) : iosNotFound(r, module) };
8937
9300
  const dir = path.join(r.scope, module);
@@ -9797,6 +10160,97 @@ function formatCType(t) {
9797
10160
  }
9798
10161
  }
9799
10162
  //#endregion
10163
+ //#region ../compiler/src/package-versions.ts
10164
+ function compare$1(a, b) {
10165
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
10166
+ const d = (a[i] ?? 0) - (b[i] ?? 0);
10167
+ if (d) return d;
10168
+ }
10169
+ return 0;
10170
+ }
10171
+ function pessimisticUpper(v) {
10172
+ const head = v.length > 1 ? v.slice(0, -1) : [...v];
10173
+ head[head.length - 1] += 1;
10174
+ return head;
10175
+ }
10176
+ const POD_OPERATORS = {
10177
+ "=": (v) => ({
10178
+ lo: {
10179
+ v,
10180
+ inclusive: true
10181
+ },
10182
+ hi: {
10183
+ v,
10184
+ inclusive: true
10185
+ }
10186
+ }),
10187
+ ">=": (v) => ({ lo: {
10188
+ v,
10189
+ inclusive: true
10190
+ } }),
10191
+ ">": (v) => ({ lo: {
10192
+ v,
10193
+ inclusive: false
10194
+ } }),
10195
+ "<=": (v) => ({ hi: {
10196
+ v,
10197
+ inclusive: true
10198
+ } }),
10199
+ "<": (v) => ({ hi: {
10200
+ v,
10201
+ inclusive: false
10202
+ } }),
10203
+ "~>": (v) => ({
10204
+ lo: {
10205
+ v,
10206
+ inclusive: true
10207
+ },
10208
+ hi: {
10209
+ v: pessimisticUpper(v),
10210
+ inclusive: false
10211
+ }
10212
+ })
10213
+ };
10214
+ function intersect(a, b) {
10215
+ const pick = (x, y, sign) => {
10216
+ if (!x) return y;
10217
+ if (!y) return x;
10218
+ const d = compare$1(x.v, y.v) * sign;
10219
+ if (d !== 0) return d > 0 ? x : y;
10220
+ return {
10221
+ v: x.v,
10222
+ inclusive: x.inclusive && y.inclusive
10223
+ };
10224
+ };
10225
+ return {
10226
+ lo: pick(a.lo, b.lo, 1),
10227
+ hi: pick(a.hi, b.hi, -1)
10228
+ };
10229
+ }
10230
+ function isEmpty(r) {
10231
+ if (!r.lo || !r.hi) return false;
10232
+ const d = compare$1(r.lo.v, r.hi.v);
10233
+ return d > 0 || d === 0 && !(r.lo.inclusive && r.hi.inclusive);
10234
+ }
10235
+ function podRange(requirement) {
10236
+ let range = {};
10237
+ for (const part of requirement.split(",")) {
10238
+ const m = /^\s*(~>|>=|<=|>|<|=)?\s*(\d+(?:\.\d+)*)\s*$/.exec(part);
10239
+ if (!m) return void 0;
10240
+ range = intersect(range, POD_OPERATORS[m[1] ?? "="](m[2].split(".").map(Number)));
10241
+ }
10242
+ return range;
10243
+ }
10244
+ function podsCompatible(a, b) {
10245
+ const ra = podRange(a);
10246
+ const rb = podRange(b);
10247
+ return !ra || !rb || !isEmpty(intersect(ra, rb));
10248
+ }
10249
+ function compareVersions(a, b) {
10250
+ return compare$1(a.split(".").map(Number), b.split(".").map(Number));
10251
+ }
10252
+ const gradleCompatible = (a, b) => !a.endsWith("!!") && !b.endsWith("!!");
10253
+ //#endregion
9800
10254
  //#region ../compiler/src/sdk/schema.ts
9801
10255
  const MIN_IOS = "15.1";
9802
10256
  const JNI_PRIM$1 = {
@@ -9816,9 +10270,13 @@ function parseSdkType(s, module = "", typeParams = []) {
9816
10270
  }
9817
10271
  let sdkOptions = {};
9818
10272
  let deferredPlatforms = [];
10273
+ function oldestIos() {
10274
+ const target = sdkOptions.ios?.deploymentTarget;
10275
+ return target && compareVersions(target, "15.1") > 0 ? target : MIN_IOS;
10276
+ }
9819
10277
  function withSdkOptions(opts, f, deferred = []) {
9820
10278
  const saved = [sdkOptions, deferredPlatforms];
9821
- sdkOptions = opts ?? {};
10279
+ sdkOptions = { ...opts };
9822
10280
  deferredPlatforms = deferred;
9823
10281
  try {
9824
10282
  return f();
@@ -9826,6 +10284,10 @@ function withSdkOptions(opts, f, deferred = []) {
9826
10284
  [sdkOptions, deferredPlatforms] = saved;
9827
10285
  }
9828
10286
  }
10287
+ const WRAP_UNBOUND = {
10288
+ ios: "wrap it in Swift of your own whose types Lucent binds, in a local pod the app depends on",
10289
+ android: "wrap it in Kotlin of your own whose types Lucent binds, in a Gradle module the app depends on"
10290
+ };
9829
10291
  function platformSdkTyped(platform) {
9830
10292
  return !deferredPlatforms.includes(platform) && sdkAvailable(platform, sdkOptions);
9831
10293
  }
@@ -9852,6 +10314,9 @@ function sdkNamesOf(platform, module) {
9852
10314
  const n = sdkNames(platform, module, sdkOptions);
9853
10315
  return "names" in n ? n.names : void 0;
9854
10316
  }
10317
+ function sdkCacheDir() {
10318
+ return sdkOptions.cacheDir;
10319
+ }
9855
10320
  function currentSdkIdentity() {
9856
10321
  return sdkIdentity(sdkOptions);
9857
10322
  }
@@ -9894,6 +10359,7 @@ function jniDescriptor(params, returns, typeParams = []) {
9894
10359
  case "id":
9895
10360
  case "record":
9896
10361
  case "set":
10362
+ case "tuple":
9897
10363
  case "out":
9898
10364
  case "fn":
9899
10365
  case "error": return fail$1(`${t.k} is not a Java type`);
@@ -9954,12 +10420,261 @@ function blockConversion(t) {
9954
10420
  passed: true
9955
10421
  }, sdkTypeFacts("ios"));
9956
10422
  }
10423
+ function kotlinFunctionConversion(t) {
10424
+ return planConversion({
10425
+ ...t,
10426
+ nullable: false
10427
+ }, {
10428
+ backend: "jni",
10429
+ platform: "android",
10430
+ flow: "in",
10431
+ passed: true
10432
+ }, sdkTypeFacts("android"));
10433
+ }
10434
+ //#endregion
10435
+ //#region ../compiler/src/sdk/view-rules.ts
10436
+ const ROOT_VIEW = {
10437
+ ios: {
10438
+ module: "UIKit",
10439
+ name: "UIView"
10440
+ },
10441
+ android: {
10442
+ module: "android.view",
10443
+ name: "View"
10444
+ }
10445
+ };
10446
+ const LISTENER = /^setOn([A-Z]\w*)Listener$/;
10447
+ const SETTER = /^set([A-Z]\w*)$/;
10448
+ const REGISTER = "addAction:forControlEvents:";
10449
+ const INSERT_AT = /^insert\w*:atIndex:$/;
10450
+ const capitalized = (s) => s[0].toUpperCase() + s.slice(1);
10451
+ const decapitalized = (s) => s[0].toLowerCase() + s.slice(1);
10452
+ const singleBit = (value) => typeof value === "number" && value > 0 && (value & value - 1) === 0;
10453
+ function referenced(type, schema, find) {
10454
+ if (type.k !== "ref") return void 0;
10455
+ const decl = type.module === schema.module ? schema.types.find((t) => t.name === type.name) : find(type.module, type.name);
10456
+ return {
10457
+ module: type.module,
10458
+ name: type.name,
10459
+ decl
10460
+ };
10461
+ }
10462
+ function viewRules(cls, schema, find) {
10463
+ const types = ownTypes(schema);
10464
+ const where = schema.provenance?.artifact ?? schema.module;
10465
+ const why = (member, role) => unsupportedReason(planBinding(cls, member, schema, types, role));
10466
+ const props = [];
10467
+ const events = [];
10468
+ const refused = [];
10469
+ for (const p of cls.properties ?? []) {
10470
+ if (p.static || p.readonly || p.value !== void 0) continue;
10471
+ const reason = why(p, "set");
10472
+ if (reason) refused.push({
10473
+ name: p.name,
10474
+ reason
10475
+ });
10476
+ else props.push({
10477
+ kind: "property",
10478
+ name: p.name,
10479
+ member: p,
10480
+ explanation: `${cls.name}.${p.name}: a writable property${p.setter ? ` (${p.setter})` : ""}, in ${where}`
10481
+ });
10482
+ }
10483
+ const setters = /* @__PURE__ */ new Map();
10484
+ let children;
10485
+ for (const m of cls.methods ?? []) {
10486
+ if (m.static) continue;
10487
+ const [child, index] = m.params;
10488
+ if (m.params.length === 2 && child.type.k === "ref" && index.type.k === "prim" && (schema.platform === "ios" ? !!m.selector && INSERT_AT.test(m.selector) : m.name === "addView" && child.type.module === ROOT_VIEW.android.module && child.type.name === ROOT_VIEW.android.name) && !children) {
10489
+ children = {
10490
+ insert: m,
10491
+ explanation: `${cls.name}.${m.selector ?? m.name}: inserts a view at an index, in ${where}`
10492
+ };
10493
+ continue;
10494
+ }
10495
+ const listener = LISTENER.exec(m.name);
10496
+ if (listener && m.params.length === 1) {
10497
+ const name = `on${listener[1]}`;
10498
+ const ref = referenced(m.params[0].type, schema, find);
10499
+ const iface = ref?.decl?.kind === "class" ? ref.decl : void 0;
10500
+ const method = iface?.functional ? iface.methods?.find((x) => x.name === iface.functional && x.abstract) : void 0;
10501
+ if (!ref || !iface || !method) refused.push({
10502
+ name,
10503
+ reason: `${m.name}'s listener has more than one method: set it in setup code, with an object of a class implementing it`
10504
+ });
10505
+ else events.push({
10506
+ kind: "listener",
10507
+ name,
10508
+ setter: m,
10509
+ listener: {
10510
+ module: ref.module,
10511
+ name: ref.name
10512
+ },
10513
+ method,
10514
+ explanation: `${cls.name}.${m.name}: a listener with one method (${ref.name}.${method.name}), in ${where}`
10515
+ });
10516
+ continue;
10517
+ }
10518
+ if (m.selector === REGISTER && m.params.length === 2) {
10519
+ const ref = referenced(m.params[1].type, schema, find);
10520
+ if (ref?.decl?.kind === "enum") for (const c of ref.decl.cases.filter((x) => singleBit(x.value))) events.push({
10521
+ kind: "control",
10522
+ name: `on${capitalized(c.name)}`,
10523
+ register: m,
10524
+ events: {
10525
+ module: ref.module,
10526
+ name: ref.name
10527
+ },
10528
+ value: c.value,
10529
+ explanation: `${cls.name}.${REGISTER} with ${ref.name}.${c.name}: a control event, in ${where}`
10530
+ });
10531
+ continue;
10532
+ }
10533
+ const setter = SETTER.exec(m.name);
10534
+ if (schema.platform === "android" && setter && m.params.length === 1 && m.returns.k === "prim" && m.returns.name === "void") {
10535
+ const name = decapitalized(setter[1]);
10536
+ setters.set(name, [...setters.get(name) ?? [], m]);
10537
+ }
10538
+ }
10539
+ for (const [name, overloads] of setters) {
10540
+ if (props.some((p) => p.name === name)) continue;
10541
+ if (overloads.every((m) => m.typeParams?.length)) {
10542
+ refused.push({
10543
+ name,
10544
+ reason: `${overloads[0].name} is generic, and an attribute gives no type for it`
10545
+ });
10546
+ continue;
10547
+ }
10548
+ const usable = overloads.filter((m) => !m.typeParams?.length && !why(m, "call"));
10549
+ if (!usable.length) refused.push({
10550
+ name,
10551
+ reason: why(overloads[0], "call")
10552
+ });
10553
+ else props.push({
10554
+ kind: "setter",
10555
+ name,
10556
+ overloads: usable,
10557
+ explanation: `${cls.name}.${usable[0].name}: a setter taking one value, in ${where}`
10558
+ });
10559
+ }
10560
+ return {
10561
+ props,
10562
+ events,
10563
+ refused,
10564
+ ...children ? { children } : {}
10565
+ };
10566
+ }
10567
+ function isViewClass(cls, schema, find) {
10568
+ const root = ROOT_VIEW[schema.platform];
10569
+ let owner = cls;
10570
+ let module = schema.module;
10571
+ for (let depth = 0; owner && depth < 64; depth++) {
10572
+ if (module === root.module && owner.name === root.name) return true;
10573
+ if (owner.interface || !owner.extends) return false;
10574
+ const sup = parseSdkType(owner.extends, module);
10575
+ if (sup.k !== "ref") return false;
10576
+ if (sup.module === root.module && sup.name === root.name) return true;
10577
+ if (sup.module !== module && schema.platform === "ios") return true;
10578
+ const decl = sup.module === schema.module ? schema.types.find((t) => t.name === sup.name) : find(sup.module, sup.name);
10579
+ owner = decl?.kind === "class" ? decl : void 0;
10580
+ module = sup.module;
10581
+ }
10582
+ return false;
10583
+ }
10584
+ function viewConstruction(cls, schema, find) {
10585
+ if (schema.platform === "android") {
10586
+ const ctor = (cls.constructors ?? []).find((c) => !c.protected && c.params.length === 1 && c.params[0].type.k === "ref" && c.params[0].type.module === "android.content" && c.params[0].type.name === "Context");
10587
+ return ctor ? {
10588
+ kind: "context",
10589
+ ctor,
10590
+ owner: cls.name,
10591
+ module: schema.module
10592
+ } : {
10593
+ kind: "create",
10594
+ reason: `${cls.name} has no constructor taking only a Context`
10595
+ };
10596
+ }
10597
+ let owner = cls;
10598
+ let module = schema.module;
10599
+ for (let depth = 0; owner && depth < 32; depth++) {
10600
+ const ctors = owner.constructors ?? [];
10601
+ const frame = ctors.find((c) => c.selector === "initWithFrame:");
10602
+ const plain = ctors.find((c) => c.selector === "init" && !c.params.length);
10603
+ if (frame) return {
10604
+ kind: "frame",
10605
+ ctor: frame,
10606
+ owner: owner.name,
10607
+ module
10608
+ };
10609
+ if (plain) return {
10610
+ kind: "init",
10611
+ ctor: plain,
10612
+ owner: owner.name,
10613
+ module
10614
+ };
10615
+ if (ctors.length && !owner.inheritsInit) break;
10616
+ if (!owner.extends) break;
10617
+ const sup = parseSdkType(owner.extends, module);
10618
+ if (sup.k !== "ref") break;
10619
+ const decl = sup.module === schema.module ? schema.types.find((t) => t.name === sup.name) : find(sup.module, sup.name);
10620
+ owner = decl?.kind === "class" ? decl : void 0;
10621
+ module = sup.module;
10622
+ }
10623
+ return {
10624
+ kind: "create",
10625
+ reason: `${cls.name} has no initWithFrame: or init to make it with: say how, create={() => new ${cls.name}(…)}`
10626
+ };
10627
+ }
10628
+ function viewTag(cls, schema, moduleOf) {
10629
+ const find = (module, name) => moduleOf(module)?.types.find((t) => t.name === name);
10630
+ const props = /* @__PURE__ */ new Map();
10631
+ const events = /* @__PURE__ */ new Map();
10632
+ const refused = /* @__PURE__ */ new Map();
10633
+ let children;
10634
+ let owner = {
10635
+ cls,
10636
+ schema
10637
+ };
10638
+ for (let depth = 0; owner && depth < 64; depth++) {
10639
+ const rules = viewRules(owner.cls, owner.schema, find);
10640
+ for (const prop of rules.props) if (!props.has(prop.name)) props.set(prop.name, {
10641
+ prop,
10642
+ owner
10643
+ });
10644
+ for (const event of rules.events) if (!events.has(event.name)) events.set(event.name, {
10645
+ event,
10646
+ owner
10647
+ });
10648
+ if (rules.children && !children) children = {
10649
+ rule: rules.children,
10650
+ owner
10651
+ };
10652
+ for (const r of rules.refused) if (!refused.has(r.name)) refused.set(r.name, r.reason);
10653
+ const root = ROOT_VIEW[schema.platform];
10654
+ if (owner.schema.module === root.module && owner.cls.name === root.name) break;
10655
+ if (!owner.cls.extends) break;
10656
+ const sup = parseSdkType(owner.cls.extends, owner.schema.module);
10657
+ const next = sup.k === "ref" ? moduleOf(sup.module) : void 0;
10658
+ const decl = sup.k === "ref" ? next?.types.find((t) => t.name === sup.name) : void 0;
10659
+ owner = next && decl?.kind === "class" ? {
10660
+ cls: decl,
10661
+ schema: next
10662
+ } : void 0;
10663
+ }
10664
+ return {
10665
+ props,
10666
+ events,
10667
+ ...children ? { children } : {},
10668
+ refused,
10669
+ construction: viewConstruction(cls, schema, find)
10670
+ };
10671
+ }
9957
10672
  //#endregion
9958
10673
  //#region ../compiler/src/sdk/dts.ts
9959
- function sdkDts(schema) {
9960
- const plain = emitDts(schema, /* @__PURE__ */ new Map());
10674
+ function sdkDts(schema, options = {}) {
10675
+ const plain = emitDts(schema, /* @__PURE__ */ new Map(), options);
9961
10676
  const aliases = importAliases(schema, plain.imports);
9962
- return aliases.size ? emitDts(schema, aliases).text : plain.text;
10677
+ return aliases.size ? emitDts(schema, aliases, options).text : plain.text;
9963
10678
  }
9964
10679
  function importAliases(schema, imports) {
9965
10680
  const local = new Set(schema.types.map((t) => t.name));
@@ -9970,7 +10685,7 @@ function importAliases(schema, imports) {
9970
10685
  return aliases;
9971
10686
  }
9972
10687
  const moduleIdent = (module) => module.replace(/^lucent:/, "").replace(/^(ios|android)\//, "").replace(/\W/g, "_");
9973
- function emitDts(schema, aliases) {
10688
+ function emitDts(schema, aliases, options) {
9974
10689
  const imports = /* @__PURE__ */ new Map();
9975
10690
  const use = (module, name) => {
9976
10691
  const names = imports.get(module) ?? /* @__PURE__ */ new Set();
@@ -9995,6 +10710,10 @@ function emitDts(schema, aliases) {
9995
10710
  use("lucent:ios", "Out");
9996
10711
  return ref("Out", tsType(t.of, true));
9997
10712
  case "set": return ref("Set", tsType(t.of, out));
10713
+ case "tuple": return tuple(t.of.map((x, i) => ({
10714
+ type: tsType(x, out),
10715
+ ...t.labels ? { name: t.labels[i] } : {}
10716
+ })));
9998
10717
  case "array":
9999
10718
  if (t.of.k === "prim" && t.of.name === "byte" && !t.list) return ref("Uint8Array");
10000
10719
  return array(tsType(t.of, out));
@@ -10042,7 +10761,7 @@ function emitDts(schema, aliases) {
10042
10761
  type: tsType(parseSdkType(f.type, schema.module))
10043
10762
  })))
10044
10763
  }, blank);
10045
- else body.push(...classDts(schema, type, tsType, use), blank);
10764
+ else body.push(...classDts(schema, type, tsType, use, options), blank);
10046
10765
  const refused = refusalDoc(schema);
10047
10766
  for (const f of schema.functions ?? []) {
10048
10767
  const tps = f.typeParams ?? [];
@@ -10213,7 +10932,7 @@ const RESERVED$3 = /* @__PURE__ */ new Set([
10213
10932
  function safeName(n) {
10214
10933
  return RESERVED$3.has(n) ? `${n}_` : n;
10215
10934
  }
10216
- function classDts(schema, cls, tsType, use) {
10935
+ function classDts(schema, cls, tsType, use, options) {
10217
10936
  const parse = (s, tps = []) => parseSdkType(s, schema.module, tps);
10218
10937
  const oneOf = (refs, type, out) => {
10219
10938
  if (!refs) return tsType(type, out);
@@ -10306,10 +11025,12 @@ function classDts(schema, cls, tsType, use) {
10306
11025
  const methodNames = new Set((cls.methods ?? []).map((m) => `${!!m.static}:${m.name}`));
10307
11026
  for (const p of (cls.properties ?? []).filter((x) => !methodNames.has(`${!!x.static}:${x.name}`))) {
10308
11027
  const type = p.value !== void 0 && p.static && p.readonly ? literal$3(constantValue$1(parse(p.type), p.value)) : settled(p, oneOf(p.oneOf, result(parse(p.type)), true));
11028
+ const set = p.readonly || schema.platform !== "android" ? void 0 : oneOf(p.oneOf, parse(p.type), false);
10309
11029
  members.push({
10310
11030
  k: "property",
10311
11031
  name: p.name,
10312
11032
  type,
11033
+ ...set && printType(set) !== printType(type) ? { set } : {},
10313
11034
  ...p.static ? { static: true } : {},
10314
11035
  ...p.readonly ? { readonly: true } : {},
10315
11036
  ...memberDoc(p)
@@ -10374,6 +11095,23 @@ function classDts(schema, cls, tsType, use) {
10374
11095
  params: [],
10375
11096
  ret: keyword$1("void")
10376
11097
  });
11098
+ const jsx = options.jsx ? jsxAttributes(schema, cls, tsType, parse) : void 0;
11099
+ if (jsx?.root) members.push({
11100
+ k: "property",
11101
+ name: "~jsx",
11102
+ type: ref(use("lucent:ui", "NativeAttributes"), ref("this")),
11103
+ readonly: true,
11104
+ optional: true,
11105
+ doc: "The JSX attributes of this view's tag: its classes' `~jsx:` keys, together."
11106
+ });
11107
+ if (jsx?.decl) members.push({
11108
+ k: "property",
11109
+ name: `~jsx:${schema.module}.${cls.name}`,
11110
+ type: ref(jsx.name, ref("this"), ...typeParams.map((t) => ref(t.name))),
11111
+ readonly: true,
11112
+ optional: true,
11113
+ doc: "The JSX attributes this class gives its tag, derived by rule from its declarations."
11114
+ });
10377
11115
  const out = [{
10378
11116
  k: "class",
10379
11117
  name: cls.name,
@@ -10391,8 +11129,63 @@ function classDts(schema, cls, tsType, use) {
10391
11129
  extends: supers,
10392
11130
  members: []
10393
11131
  });
11132
+ if (jsx?.decl) out.push(jsx.decl);
10394
11133
  return out;
10395
11134
  }
11135
+ function jsxAttributes(schema, cls, tsType, parse) {
11136
+ const find = (module, name) => findSdkType(schema.platform, module, name);
11137
+ if (cls.interface || !isViewClass(cls, schema, find)) return void 0;
11138
+ const view = ROOT_VIEW[schema.platform];
11139
+ const root = schema.module === view.module && cls.name === view.name;
11140
+ const rules = viewRules(cls, schema, find);
11141
+ const childrenMember = (c) => {
11142
+ const child = tsType(parseSdkType(`${view.module}.${view.name}`), false);
11143
+ return {
11144
+ k: "property",
11145
+ name: "children",
11146
+ type: union$1([child, readonlyArray(child)]),
11147
+ optional: true,
11148
+ doc: c.explanation
11149
+ };
11150
+ };
11151
+ const name = `__jsx_${cls.name}`;
11152
+ if (!rules.props.length && !rules.events.length && !rules.children) return root ? {
11153
+ name,
11154
+ root
11155
+ } : void 0;
11156
+ const props = rules.props.map((p) => ({
11157
+ k: "property",
11158
+ name: p.name,
11159
+ type: p.kind === "property" ? tsType(parse(p.member.type), false) : union$1(p.overloads.map((m) => tsType(parse(m.params[0].type), false))),
11160
+ optional: true,
11161
+ doc: p.explanation
11162
+ }));
11163
+ const events = rules.events.map((e) => ({
11164
+ k: "property",
11165
+ name: e.name,
11166
+ type: e.kind === "listener" ? fn$3(e.method.params.map((x, i) => param$2(`arg${i}`, tsType(parseSdkType(x.type, e.listener.module), true))), tsType(parseSdkType(e.method.returns, e.listener.module), false)) : fn$3([param$2("control", ref("Self"))], keyword$1("void")),
11167
+ optional: true,
11168
+ doc: e.explanation
11169
+ }));
11170
+ return {
11171
+ name,
11172
+ root,
11173
+ decl: {
11174
+ k: "interface",
11175
+ name,
11176
+ local: true,
11177
+ typeParams: [{ name: "Self" }, ...distinctTypeParams(cls.typeParams ?? []).map((name) => ({
11178
+ name,
11179
+ default: keyword$1("unknown")
11180
+ }))],
11181
+ members: [
11182
+ ...props,
11183
+ ...events,
11184
+ ...rules.children ? [childrenMember(rules.children)] : []
11185
+ ]
11186
+ }
11187
+ };
11188
+ }
10396
11189
  function namedLikeAncestor(schema, cls) {
10397
11190
  let ext = cls.extends ? parseSdkType(cls.extends, schema.module) : void 0;
10398
11191
  for (let depth = 0; ext?.k === "ref" && depth < 32; depth++) {
@@ -10721,96 +11514,165 @@ function constantValue$1(t, value) {
10721
11514
  return isBigIntType(t) ? BigInt(value) : value;
10722
11515
  }
10723
11516
  //#endregion
10724
- //#region ../compiler/src/package-versions.ts
10725
- function compare$1(a, b) {
10726
- for (let i = 0; i < Math.max(a.length, b.length); i++) {
10727
- const d = (a[i] ?? 0) - (b[i] ?? 0);
10728
- if (d) return d;
10729
- }
10730
- return 0;
11517
+ //#region ../compiler/src/sdk/declaration-cache.ts
11518
+ let version$1;
11519
+ function declarationsVersion() {
11520
+ if (version$1) return version$1;
11521
+ return version$1 = "df570a79";
11522
+ }
11523
+ function cachedDeclarations(cacheDir, identity, key, make) {
11524
+ const name = crypto.createHash("sha256").update([
11525
+ declarationsVersion(),
11526
+ identity,
11527
+ ...key
11528
+ ].join("\n")).digest("hex").slice(0, 24);
11529
+ const file = path.join(cacheRoot(cacheDir), "declarations", `${name}.d.ts`);
11530
+ try {
11531
+ return fs.readFileSync(file, "utf8");
11532
+ } catch {}
11533
+ const text = make();
11534
+ const tmp = `${file}.${process.pid}.${crypto.randomUUID()}.tmp`;
11535
+ fs.mkdirSync(path.dirname(file), { recursive: true });
11536
+ fs.writeFileSync(tmp, text);
11537
+ fs.renameSync(tmp, file);
11538
+ return text;
10731
11539
  }
10732
- function pessimisticUpper(v) {
10733
- const head = v.length > 1 ? v.slice(0, -1) : [...v];
10734
- head[head.length - 1] += 1;
10735
- return head;
11540
+ //#endregion
11541
+ //#region ../compiler/src/sdk/native-jsx-dts.ts
11542
+ const NATIVE_JSX_UI = ["NativeViewTag"];
11543
+ function rootViews(platforms) {
11544
+ const alias = (p) => `${p}_${ROOT_VIEW[p].name}`;
11545
+ return {
11546
+ imports: platforms.map((p) => ({
11547
+ k: "importType",
11548
+ names: [`${ROOT_VIEW[p].name} as ${alias(p)}`],
11549
+ from: `lucent:${p}/${ROOT_VIEW[p].module}`
11550
+ })),
11551
+ types: platforms.map((p) => ref(alias(p)))
11552
+ };
10736
11553
  }
10737
- const POD_OPERATORS = {
10738
- "=": (v) => ({
10739
- lo: {
10740
- v,
10741
- inclusive: true
10742
- },
10743
- hi: {
10744
- v,
10745
- inclusive: true
10746
- }
10747
- }),
10748
- ">=": (v) => ({ lo: {
10749
- v,
10750
- inclusive: true
10751
- } }),
10752
- ">": (v) => ({ lo: {
10753
- v,
10754
- inclusive: false
10755
- } }),
10756
- "<=": (v) => ({ hi: {
10757
- v,
10758
- inclusive: true
10759
- } }),
10760
- "<": (v) => ({ hi: {
10761
- v,
10762
- inclusive: false
10763
- } }),
10764
- "~>": (v) => ({
10765
- lo: {
10766
- v,
10767
- inclusive: true
10768
- },
10769
- hi: {
10770
- v: pessimisticUpper(v),
10771
- inclusive: false
11554
+ const nativeTags = (roots) => roots.map((r) => ref("NativeViewTag", r));
11555
+ function nativeJsxDecls() {
11556
+ return [{
11557
+ k: "interface",
11558
+ name: "ElementAttributesProperty",
11559
+ members: [{
11560
+ k: "property",
11561
+ name: "~jsx",
11562
+ type: object([])
11563
+ }]
11564
+ }, {
11565
+ k: "interface",
11566
+ name: "IntrinsicClassAttributes",
11567
+ typeParams: [{ name: "T" }],
11568
+ members: [{
11569
+ k: "property",
11570
+ name: "create",
11571
+ type: fn$3([], ref("T")),
11572
+ optional: true,
11573
+ doc: "Makes the view, where its class has no frame or Context constructor to make it with."
11574
+ }]
11575
+ }];
11576
+ }
11577
+ //#endregion
11578
+ //#region ../compiler/src/sdk/declarations.ts
11579
+ function classOfDecl(decl) {
11580
+ const sdk = sdkModuleOf(decl.getSourceFile());
11581
+ if (!sdk) return void 0;
11582
+ const owner = ts.isClassDeclaration(decl) ? decl : decl.parent;
11583
+ if (!owner || !ts.isClassDeclaration(owner) || !owner.name) return void 0;
11584
+ const cls = findSdkType(sdk.platform, sdk.module, owner.name.text);
11585
+ return cls?.kind === "class" ? {
11586
+ ...sdk,
11587
+ cls
11588
+ } : void 0;
11589
+ }
11590
+ function sdkInterfacesOf(checker, decl) {
11591
+ const out = [];
11592
+ for (const h of decl.heritageClauses ?? []) {
11593
+ if (h.token !== ts.SyntaxKind.ImplementsKeyword) continue;
11594
+ for (const t of h.types) {
11595
+ const d = checker.getTypeAtLocation(t).getSymbol()?.declarations?.find(ts.isClassDeclaration);
11596
+ const ref = d ? classOfDecl(d) : void 0;
11597
+ if (ref?.cls.interface) out.push(ref);
10772
11598
  }
10773
- })
10774
- };
10775
- function intersect(a, b) {
10776
- const pick = (x, y, sign) => {
10777
- if (!x) return y;
10778
- if (!y) return x;
10779
- const d = compare$1(x.v, y.v) * sign;
10780
- if (d !== 0) return d > 0 ? x : y;
10781
- return {
10782
- v: x.v,
10783
- inclusive: x.inclusive && y.inclusive
11599
+ }
11600
+ return out;
11601
+ }
11602
+ function requirementOf(checker, m) {
11603
+ const cls = m.parent;
11604
+ if (!ts.isClassLike(cls) || !ts.isIdentifier(m.name)) return void 0;
11605
+ for (const protocol of sdkInterfacesOf(checker, cls)) {
11606
+ const method = protocol.cls.methods?.find((x) => !x.static && x.name === m.name.text);
11607
+ if (method) return {
11608
+ protocol,
11609
+ method,
11610
+ main: !!(protocol.cls.mainActor || method.mainActor)
10784
11611
  };
11612
+ }
11613
+ }
11614
+ function schemaMethod(ref, decl) {
11615
+ const inherited = inheritedFrom(ref, decl);
11616
+ if (inherited) return {
11617
+ ref: inherited.ref,
11618
+ method: inherited.ref.cls.methods[inherited.index],
11619
+ promise: false
10785
11620
  };
10786
- return {
10787
- lo: pick(a.lo, b.lo, 1),
10788
- hi: pick(a.hi, b.hi, -1)
10789
- };
11621
+ const name = decl.name.text;
11622
+ const index = decl.parent.members.filter((m) => ts.isMethodDeclaration(m) && m.name.text === name).indexOf(decl);
11623
+ return (ref.cls.methods ?? []).flatMap((m) => [...m.name === name ? [{
11624
+ ref,
11625
+ method: m,
11626
+ promise: false
11627
+ }] : [], ...m.async && declaresPromise(ref.cls, m) && (m.async.name ?? m.name) === name ? [{
11628
+ ref,
11629
+ method: m,
11630
+ promise: true
11631
+ }] : []])[index];
10790
11632
  }
10791
- function isEmpty(r) {
10792
- if (!r.lo || !r.hi) return false;
10793
- const d = compare$1(r.lo.v, r.hi.v);
10794
- return d > 0 || d === 0 && !(r.lo.inclusive && r.hi.inclusive);
11633
+ function schemaProperty(ref, decl) {
11634
+ const inherited = inheritedFrom(ref, decl);
11635
+ if (inherited) return {
11636
+ ref: inherited.ref,
11637
+ property: inherited.ref.cls.properties[inherited.index]
11638
+ };
11639
+ const name = decl.name.text;
11640
+ const isStatic = !!ts.getModifiers(decl)?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);
11641
+ const property = ref.cls.properties?.find((p) => p.name === name && !!p.static === isStatic);
11642
+ return property ? {
11643
+ ref,
11644
+ property
11645
+ } : void 0;
10795
11646
  }
10796
- function podRange(requirement) {
10797
- let range = {};
10798
- for (const part of requirement.split(",")) {
10799
- const m = /^\s*(~>|>=|<=|>|<|=)?\s*(\d+(?:\.\d+)*)\s*$/.exec(part);
10800
- if (!m) return void 0;
10801
- range = intersect(range, POD_OPERATORS[m[1] ?? "="](m[2].split(".").map(Number)));
10802
- }
10803
- return range;
11647
+ const isSdkPropertyDecl = (d) => ts.isPropertyDeclaration(d) || ts.isGetAccessorDeclaration(d) || ts.isSetAccessorDeclaration(d);
11648
+ function inheritedFrom(ref, decl) {
11649
+ const tag = ts.getJSDocTags(decl).find((t) => `@${t.tagName.text}` === INHERITED_TAG);
11650
+ if (!tag) return void 0;
11651
+ const [owner, index] = (ts.getTextOfJSDocComment(tag.comment) ?? "").split(" ");
11652
+ const dot = owner.lastIndexOf(".");
11653
+ const module = owner.slice(0, dot);
11654
+ const cls = findSdkType(ref.platform, module, owner.slice(dot + 1));
11655
+ if (cls?.kind !== "class") throw new Error(`${owner}: no class for an inherited member`);
11656
+ return {
11657
+ ref: {
11658
+ ...ref,
11659
+ module,
11660
+ cls
11661
+ },
11662
+ index: Number(index)
11663
+ };
10804
11664
  }
10805
- function podsCompatible(a, b) {
10806
- const ra = podRange(a);
10807
- const rb = podRange(b);
10808
- return !ra || !rb || !isEmpty(intersect(ra, rb));
11665
+ function schemaConstructor(ref, decl) {
11666
+ return ref.cls.constructors[decl.parent.members.filter(ts.isConstructorDeclaration).indexOf(decl)];
10809
11667
  }
10810
- function compareVersions(a, b) {
10811
- return compare$1(a.split(".").map(Number), b.split(".").map(Number));
11668
+ function promiseForm(m) {
11669
+ const { throws: _, ...rest } = m;
11670
+ return {
11671
+ ...rest,
11672
+ params: m.params.slice(0, -1),
11673
+ returns: m.async.returns
11674
+ };
10812
11675
  }
10813
- const gradleCompatible = (a, b) => !a.endsWith("!!") && !b.endsWith("!!");
10814
11676
  //#endregion
10815
11677
  //#region ../compiler/src/sdk/toolkit-forms.ts
10816
11678
  const FORMS = { SwiftUI: [{
@@ -10935,7 +11797,7 @@ function toolkitDts(toolkit, schema) {
10935
11797
  const overloads = (owner, m, name) => {
10936
11798
  const refused = unsupportedReason(planBinding(owner, m, schema, ownTypes(schema)));
10937
11799
  const since = String(m.since ?? owner?.since ?? "0");
10938
- const newer = compareVersions(since, MIN_IOS) > 0;
11800
+ const newer = compareVersions(since, oldestIos()) > 0;
10939
11801
  const doc = (form) => [
10940
11802
  ...refused ? [`Lucent cannot write this in a body yet: ${refused}.`] : [],
10941
11803
  ...m.deprecated ? ["@deprecated"] : [],
@@ -11162,11 +12024,12 @@ function toolkitDts(toolkit, schema) {
11162
12024
  return printUnit({
11163
12025
  banner: `Generated by Lucent from ${schema.provenance?.artifact ?? schema.module} (${schema.module}, written as source). Do not edit.`,
11164
12026
  decls: [
11165
- ...forms.size ? [{
12027
+ {
11166
12028
  k: "importType",
11167
- names: [...forms].sort(),
12029
+ names: [.../* @__PURE__ */ new Set([...forms, ...NATIVE_JSX_UI])].sort(),
11168
12030
  from: "lucent:ui"
11169
- }] : [],
12031
+ },
12032
+ ...rootViews([toolkit.platform]).imports,
11170
12033
  ...decls,
11171
12034
  ...modifierDecls,
11172
12035
  ...namespaces,
@@ -11308,6 +12171,7 @@ const method = (o) => ({
11308
12171
  });
11309
12172
  function fixedDecls(toolkit) {
11310
12173
  const view = ref(toolkit.source.view);
12174
+ const [root] = rootViews([toolkit.platform]).types;
11311
12175
  const shown = union$1([
11312
12176
  view,
11313
12177
  literal$3(false),
@@ -11343,8 +12207,14 @@ function fixedDecls(toolkit) {
11343
12207
  {
11344
12208
  k: "typeAlias",
11345
12209
  name: "Element",
11346
- type: view
12210
+ type: intersection([view, root])
12211
+ },
12212
+ {
12213
+ k: "typeAlias",
12214
+ name: "ElementType",
12215
+ type: union$1([fn$3([param$2("props", keyword$1("never"))], view), ...nativeTags([root])])
11347
12216
  },
12217
+ ...nativeJsxDecls(),
11348
12218
  {
11349
12219
  k: "interface",
11350
12220
  name: "ElementChildrenAttribute",
@@ -11545,164 +12415,6 @@ function toolkit(name) {
11545
12415
  return TOOLKITS[name];
11546
12416
  }
11547
12417
  //#endregion
11548
- //#region ../compiler/src/ui/roots.ts
11549
- const ROOT_VIEWS = {
11550
- ios: {
11551
- module: "UIKit",
11552
- name: "UIView"
11553
- },
11554
- android: {
11555
- module: "android.view",
11556
- name: "View"
11557
- }
11558
- };
11559
- const SLOT_VIEWS = {
11560
- ios: {
11561
- module: "UIKit",
11562
- name: "UIView"
11563
- },
11564
- android: {
11565
- module: "android.view",
11566
- name: "ViewGroup"
11567
- }
11568
- };
11569
- const sdkClassOf = (classes) => (decl) => {
11570
- const sdk = sdkModuleOf(decl.getSourceFile());
11571
- const found = sdk && classes[sdk.platform];
11572
- return found && found.module === sdk.module && decl.name?.text === found.name ? sdk.platform : void 0;
11573
- };
11574
- function toolkitOf(root) {
11575
- const toolkit = toolkitOfModule(root.module);
11576
- return toolkit && TOOLKITS[toolkit].root === root.name ? toolkit : void 0;
11577
- }
11578
- const sdkRootView = sdkClassOf(ROOT_VIEWS);
11579
- const sdkRoot = (decl) => {
11580
- const builtin = builtinSdkModuleOf(decl.getSourceFile());
11581
- const toolkit = builtin && toolkitOf({
11582
- module: builtin,
11583
- name: decl.name?.text ?? ""
11584
- });
11585
- return toolkit ? TOOLKITS[toolkit].platform : sdkRootView(decl);
11586
- };
11587
- const sdkSlot = sdkClassOf(SLOT_VIEWS);
11588
- function returnShape(checker, fn, platform, rootOf) {
11589
- const signature = checker.getSignatureFromDeclaration(fn);
11590
- const declared = signature ? checker.getReturnTypeOfSignature(signature) : void 0;
11591
- const promised = declared && promisedType(checker, declared);
11592
- const viewOf = (t) => viewClass(checker, t, rootOf);
11593
- const isView = (t) => {
11594
- const found = viewOf(t);
11595
- return found && (!platform || found.platform === platform) ? found.decl : void 0;
11596
- };
11597
- if (promised) return members(promised).some(isView) ? { kind: "promised" } : { kind: "value" };
11598
- const returned = returnedExpressions(checker, fn, platform).map((e) => checker.getTypeAtLocation(e));
11599
- const types = (fn.body ? returned : declared ? [declared] : []).flatMap(members);
11600
- const views = [];
11601
- let other;
11602
- let viewName = "";
11603
- for (const t of types) {
11604
- if (t.flags & ts.TypeFlags.Any || viewOf(t) && !isView(t)) continue;
11605
- const cls = isView(t);
11606
- if (cls) {
11607
- views.push(cls);
11608
- viewName ||= checker.typeToString(t);
11609
- } else other ??= checker.typeToString(t);
11610
- }
11611
- if (!views.length) return { kind: "value" };
11612
- if (other !== void 0) return {
11613
- kind: "ambiguous",
11614
- view: viewName,
11615
- other
11616
- };
11617
- return {
11618
- kind: "view",
11619
- root: commonClass(checker, views)
11620
- };
11621
- }
11622
- function classIdentity(checker, returned) {
11623
- const decl = ancestors(checker, returned).find((c) => c.getSourceFile().isDeclarationFile) ?? returned;
11624
- const sf = decl.getSourceFile();
11625
- return {
11626
- module: sdkModuleOf(sf)?.module ?? builtinSdkModuleOf(sf) ?? path.basename(sf.fileName, ".d.ts"),
11627
- name: decl.name?.text ?? ""
11628
- };
11629
- }
11630
- function members(t) {
11631
- return t.isUnion() ? t.types.flatMap(members) : elementsOf(t) ?? [t];
11632
- }
11633
- function elementsOf(t) {
11634
- if (!t.isIntersection()) return void 0;
11635
- return t.types.every((m) => {
11636
- const decl = m.getSymbol()?.declarations?.[0];
11637
- return !!decl && ts.isInterfaceDeclaration(decl) && !!toolkitElement(decl);
11638
- }) ? t.types : void 0;
11639
- }
11640
- function promisedType(checker, t) {
11641
- const name = t.getSymbol()?.getName();
11642
- if (name !== "Promise" && name !== "PromiseLike") return void 0;
11643
- return checker.getTypeArguments(t)[0];
11644
- }
11645
- function viewClass(checker, t, rootOf) {
11646
- const decl = t.getSymbol()?.declarations?.[0];
11647
- if (decl && ts.isInterfaceDeclaration(decl)) return toolkitElement(decl);
11648
- if (!decl || !ts.isClassDeclaration(decl)) return void 0;
11649
- for (const c of ancestors(checker, decl)) {
11650
- const platform = rootOf(c);
11651
- if (platform) return {
11652
- decl,
11653
- platform
11654
- };
11655
- }
11656
- }
11657
- function toolkitElement(decl) {
11658
- const sf = decl.getSourceFile();
11659
- const name = toolkitOfModule(builtinSdkModuleOf(sf));
11660
- const found = name && toolkit(name);
11661
- if (!found || found.element !== decl.name.text) return void 0;
11662
- const root = sf.statements.find((s) => ts.isClassDeclaration(s) && s.name?.text === found.root);
11663
- return root && {
11664
- decl: root,
11665
- platform: found.platform
11666
- };
11667
- }
11668
- function toolkitRootType(checker, t) {
11669
- const [first] = elementsOf(t) ?? [t];
11670
- const decl = first?.getSymbol()?.declarations?.[0];
11671
- const root = decl && ts.isInterfaceDeclaration(decl) ? toolkitElement(decl) : void 0;
11672
- return root?.decl.name && checker.getTypeAtLocation(root.decl.name);
11673
- }
11674
- function ancestors(checker, decl) {
11675
- const out = [];
11676
- for (let c = decl; c && !out.includes(c); c = baseClass(checker, c)) out.push(c);
11677
- return out;
11678
- }
11679
- function baseClass(checker, c) {
11680
- const symbol = c.name && checker.getSymbolAtLocation(c.name);
11681
- if (!symbol) return void 0;
11682
- const type = checker.getDeclaredTypeOfSymbol(symbol);
11683
- const base = checker.getBaseTypes(type)[0]?.getSymbol()?.declarations?.[0];
11684
- return base && ts.isClassDeclaration(base) ? base : void 0;
11685
- }
11686
- function commonClass(checker, classes) {
11687
- const [first, ...rest] = classes;
11688
- const others = rest.map((c) => ancestors(checker, c));
11689
- return ancestors(checker, first).find((c) => others.every((a) => a.includes(c))) ?? first;
11690
- }
11691
- function returnedExpressions(checker, fn, platform) {
11692
- if (!fn.body) return [];
11693
- if (!ts.isBlock(fn.body)) return [fn.body];
11694
- const out = [];
11695
- const visit = (n) => {
11696
- if (ts.isFunctionLike(n)) return;
11697
- const branch = platform && branchPlatform(checker, n);
11698
- if (branch && branch !== platform) return;
11699
- if (ts.isReturnStatement(n) && n.expression) out.push(n.expression);
11700
- ts.forEachChild(n, visit);
11701
- };
11702
- ts.forEachChild(fn.body, visit);
11703
- return out;
11704
- }
11705
- //#endregion
11706
12418
  //#region ../compiler/src/types.ts
11707
12419
  const T = {
11708
12420
  number: { k: "number" },
@@ -13589,6 +14301,11 @@ function toolkitTypesPath(name) {
13589
14301
  return toolkitSource(name) ? path.join(SDK_ROOT, "toolkit", `${name}.d.ts`) : sdkLibPath(name);
13590
14302
  }
13591
14303
  const toolkitTexts = /* @__PURE__ */ new WeakMap();
14304
+ const sdkTexts = {
14305
+ plain: /* @__PURE__ */ new WeakMap(),
14306
+ jsx: /* @__PURE__ */ new WeakMap()
14307
+ };
14308
+ const stubTexts = /* @__PURE__ */ new WeakMap();
13592
14309
  function toolkitDeclarations(name) {
13593
14310
  const toolkit = TOOLKITS[name];
13594
14311
  const source = toolkitSource(name);
@@ -13626,11 +14343,26 @@ function virtualSdkText(file, direct) {
13626
14343
  const module = m[2];
13627
14344
  if (platform === "ios" && !direct.has(`${platform}/${module}`)) {
13628
14345
  const names = sdkNamesOf(platform, module);
13629
- return names ? stubDts(platform, module, names) : void 0;
14346
+ if (!names) return void 0;
14347
+ let stub = stubTexts.get(names);
14348
+ if (stub === void 0) stubTexts.set(names, stub = cachedDeclarations(sdkCacheDir(), currentSdkIdentity(), [
14349
+ "names",
14350
+ platform,
14351
+ module
14352
+ ], () => stubDts(platform, module, names)));
14353
+ return stub;
13630
14354
  }
13631
14355
  const schema = findSdkModule(platform, module);
13632
14356
  if (!schema) return void 0;
13633
- const text = sdkDts(schema);
14357
+ const jsx = fabricRequested();
14358
+ const texts = sdkTexts[jsx ? "jsx" : "plain"];
14359
+ let text = texts.get(schema);
14360
+ if (text === void 0) texts.set(schema, text = cachedDeclarations(sdkCacheDir(), currentSdkIdentity(), [
14361
+ "full",
14362
+ platform,
14363
+ module,
14364
+ ...jsx ? ["jsx"] : []
14365
+ ], () => sdkDts(schema, { jsx })));
13634
14366
  for (const r of text.matchAll(/^export \* from "lucent:(ios\/_\w+)";$/gm)) direct.add(r[1]);
13635
14367
  return text;
13636
14368
  }
@@ -13764,6 +14496,7 @@ function jsxRuntimeOf(specifier, file) {
13764
14496
  function jsxRuntimeText() {
13765
14497
  const typed = Object.keys(TOOLKITS).filter((t) => platformSdkTyped(TOOLKITS[t].platform));
13766
14498
  const elements = typed.map((t) => TOOLKITS[t].element);
14499
+ const { imports: rootImports, types: roots } = rootViews(PLATFORMS.filter((p) => platformSdkTyped(p)));
13767
14500
  return printUnit({
13768
14501
  banner: "The JSX of a shared Lucent file: each platform's toolkit's, in its code.",
13769
14502
  decls: [
@@ -13772,6 +14505,12 @@ function jsxRuntimeText() {
13772
14505
  names: [TOOLKITS[t].element],
13773
14506
  from: `lucent:${t}`
13774
14507
  })),
14508
+ {
14509
+ k: "importType",
14510
+ names: NATIVE_JSX_UI,
14511
+ from: "lucent:ui"
14512
+ },
14513
+ ...rootImports,
13775
14514
  {
13776
14515
  k: "namespace",
13777
14516
  name: "JSX",
@@ -13779,13 +14518,18 @@ function jsxRuntimeText() {
13779
14518
  {
13780
14519
  k: "typeAlias",
13781
14520
  name: "Element",
13782
- type: elements.length ? intersection(elements.map((e) => ref(e))) : keyword$1("unknown")
14521
+ type: elements.length || roots.length ? intersection([...elements.map((e) => ref(e)), ...roots]) : keyword$1("unknown")
13783
14522
  },
13784
14523
  {
13785
14524
  k: "typeAlias",
13786
14525
  name: "ElementType",
13787
- type: union$1([...elements.map((e) => fn$3([param$2("props", keyword$1("never"))], ref(e))), ...typed.length < Object.keys(TOOLKITS).length ? [fn$3([param$2("props", keyword$1("never"))], keyword$1("unknown"))] : []])
14526
+ type: union$1([
14527
+ ...elements.map((e) => fn$3([param$2("props", keyword$1("never"))], ref(e))),
14528
+ ...typed.length < Object.keys(TOOLKITS).length ? [fn$3([param$2("props", keyword$1("never"))], keyword$1("unknown"))] : [],
14529
+ ...nativeTags(roots)
14530
+ ])
13788
14531
  },
14532
+ ...nativeJsxDecls(),
13789
14533
  {
13790
14534
  k: "interface",
13791
14535
  name: "ElementChildrenAttribute",
@@ -13813,7 +14557,8 @@ function createLucentProgram(files, readSource, platform, extra = {}) {
13813
14557
  ...compilerOptions(),
13814
14558
  skipLibCheck: !extra.libCheck
13815
14559
  };
13816
- const host = compilerHost(options, readSource, directSdkImports(files, readSource));
14560
+ const direct = directSdkImports(files, readSource);
14561
+ const host = compilerHost(options, readSource, direct);
13817
14562
  const program = ts.createProgram([
13818
14563
  ...files.map((f) => path.resolve(f)),
13819
14564
  ...references.map((f) => path.resolve(f)),
@@ -13854,7 +14599,13 @@ function createLucentProgram(files, readSource, platform, extra = {}) {
13854
14599
  diagnostics.push(...bad);
13855
14600
  for (const d of [...program.getSyntacticDiagnostics(sf), ...program.getSemanticDiagnostics(sf)]) {
13856
14601
  if (d.code === 2307 && bad.some((b) => b.start !== void 0 && d.start !== void 0 && d.start >= b.start && d.start < b.start + (b.length ?? 0))) continue;
13857
- diagnostics.push(fromTs(d));
14602
+ const hint = nativeMemberHint(d, checker, direct) ?? nativeAttributeHint(d, checker) ?? initializerFactoryHint(d, checker) ?? inheritedInitializerHint(d, checker, direct);
14603
+ const diagnostic = fromTs(d);
14604
+ diagnostics.push(hint ? {
14605
+ ...diagnostic,
14606
+ message: `${diagnostic.message} ${hint.message}`,
14607
+ fix: hint.fix
14608
+ } : diagnostic);
13858
14609
  }
13859
14610
  }
13860
14611
  return {
@@ -13865,6 +14616,129 @@ function createLucentProgram(files, readSource, platform, extra = {}) {
13865
14616
  diagnostics
13866
14617
  };
13867
14618
  }
14619
+ const MISSING_MEMBER = /* @__PURE__ */ new Set([2339, 2551]);
14620
+ function nativeMemberHint(d, checker, direct) {
14621
+ if (!MISSING_MEMBER.has(d.code) || !d.file || d.start === void 0) return void 0;
14622
+ const name = nodeAt(d.file, d.start);
14623
+ const access = name.parent;
14624
+ if (!ts.isIdentifier(name) || !access || !ts.isPropertyAccessExpression(access)) return void 0;
14625
+ const type = checker.getTypeAtLocation(access.expression);
14626
+ const symbol = type.getSymbol() ?? type.aliasSymbol;
14627
+ const declared = symbol?.declarations?.[0]?.getSourceFile();
14628
+ const sdk = declared && sdkModuleOf(declared);
14629
+ if (!symbol || !sdk) return void 0;
14630
+ const spec = `lucent:${sdk.platform}/${sdk.module}`;
14631
+ if (sdk.platform === "ios" && !direct.has(`${sdk.platform}/${sdk.module}`)) return {
14632
+ message: `${symbol.name} is ${spec}'s, which no file imports: only its name is known.`,
14633
+ fix: `import from ${spec} (a type import is enough) to use ${symbol.name}'s members`
14634
+ };
14635
+ const found = sdkLookup(sdk.platform, sdk.module);
14636
+ const schema = "schema" in found ? found.schema : void 0;
14637
+ const provenance = schema?.provenance;
14638
+ if (!schema || !provenance) return void 0;
14639
+ const skipped = skippedMember(schema, symbol.name, name.text);
14640
+ if (skipped) return {
14641
+ message: `${skipped.api} is in ${provenance.artifact}, but Lucent does not bind it: ${skipped.reason}.`,
14642
+ fix: WRAP_UNBOUND[sdk.platform]
14643
+ };
14644
+ if (provenance.kind === "sdk") return void 0;
14645
+ return {
14646
+ message: `${symbol.name} is ${spec}'s, from ${provenance.artifact} as installed, which has no ${name.text}.`,
14647
+ fix: `use what ${symbol.name} declares in this version of ${sdk.module}, or install a version that has ${name.text}`
14648
+ };
14649
+ }
14650
+ const PROTECTED_CONSTRUCTOR = 2674;
14651
+ function inheritedInitializerHint(d, checker, direct) {
14652
+ if (d.code !== PROTECTED_CONSTRUCTOR && !NO_OVERLOAD.has(d.code)) return void 0;
14653
+ if (!d.file || d.start === void 0) return void 0;
14654
+ let at = nodeAt(d.file, d.start);
14655
+ while (at && !ts.isNewExpression(at)) at = at.parent;
14656
+ if (!at || !ts.isNewExpression(at)) return void 0;
14657
+ const named = checker.getSymbolAtLocation(at.expression);
14658
+ const symbol = named && named.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(named) : named;
14659
+ const declared = symbol?.declarations?.[0]?.getSourceFile();
14660
+ const sdk = declared && sdkModuleOf(declared);
14661
+ if (!symbol || !sdk) return void 0;
14662
+ let module = sdk.module;
14663
+ let name = symbol.name;
14664
+ for (let depth = 0; depth < 32; depth++) {
14665
+ const found = sdkLookup(sdk.platform, module);
14666
+ const cls = "schema" in found ? found.schema.types.find((t) => t.kind === "class" && t.name === name) : void 0;
14667
+ if (cls?.kind !== "class" || cls.constructors?.length || !cls.inheritsInit || !cls.extends) break;
14668
+ const up = parseSdkType(cls.extends, module);
14669
+ if (up.k !== "ref") break;
14670
+ [module, name] = [up.module, up.name];
14671
+ const spec = `lucent:${sdk.platform}/${module}`;
14672
+ if (module !== sdk.module && !direct.has(`${sdk.platform}/${module}`)) return {
14673
+ message: `${symbol.name}'s initializers are ${name}'s, inherited from ${spec}, which no file imports: only its name is known.`,
14674
+ fix: `import "${spec}" (a bare import is enough) to make a ${symbol.name} with ${name}'s initializers`
14675
+ };
14676
+ }
14677
+ }
14678
+ const NO_OVERLOAD = /* @__PURE__ */ new Set([
14679
+ 2554,
14680
+ 2769,
14681
+ 2345
14682
+ ]);
14683
+ function initializerFactoryHint(d, checker) {
14684
+ if (!NO_OVERLOAD.has(d.code) || !d.file || d.start === void 0) return void 0;
14685
+ let at = nodeAt(d.file, d.start);
14686
+ while (at && !ts.isNewExpression(at)) at = at.parent;
14687
+ if (!at || !ts.isNewExpression(at)) return void 0;
14688
+ const named = checker.getSymbolAtLocation(at.expression);
14689
+ const symbol = named && named.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(named) : named;
14690
+ const declared = symbol?.declarations?.[0]?.getSourceFile();
14691
+ const sdk = declared && sdkModuleOf(declared);
14692
+ if (!symbol || !sdk) return void 0;
14693
+ const found = sdkLookup(sdk.platform, sdk.module);
14694
+ const cls = "schema" in found ? found.schema.types.find((t) => t.kind === "class" && t.name === symbol.name) : void 0;
14695
+ const factories = cls?.kind === "class" ? (cls.methods ?? []).filter((m) => m.static && m.swift?.name.startsWith("init(")) : [];
14696
+ if (!factories.length) return void 0;
14697
+ const listed = factories.map((f) => `${symbol.name}.${f.name}(…) for ${f.swift.name}`);
14698
+ return {
14699
+ message: `${symbol.name}'s initializers that take the same types are its static factories, which TypeScript tells apart: ${listed.join(", ")}.`,
14700
+ fix: `call the one you mean: ${symbol.name}.${factories[0].name}(…)`
14701
+ };
14702
+ }
14703
+ function skippedMember(schema, owner, member) {
14704
+ for (const entry of schema.skipped ?? []) {
14705
+ const at = entry.indexOf(": ");
14706
+ const api = entry.slice(0, at);
14707
+ const [type, name] = api.split("(")[0].split(/\.(?=[^.]*$)/);
14708
+ if (name === member && (type === owner || type?.endsWith(`.${owner}`))) return {
14709
+ api,
14710
+ reason: entry.slice(at + 2)
14711
+ };
14712
+ }
14713
+ }
14714
+ function nativeAttributeHint(d, checker) {
14715
+ if (!MISSING_ATTRIBUTE.has(d.code) || !d.file || d.start === void 0) return void 0;
14716
+ let element = nodeAt(d.file, d.start);
14717
+ while (element && !ts.isJsxOpeningElement(element) && !ts.isJsxSelfClosingElement(element)) element = element.parent;
14718
+ if (!element) return void 0;
14719
+ const decl = nativeTagType(checker, ts.isJsxOpeningElement(element) ? element.parent : element)?.getSymbol()?.declarations?.[0];
14720
+ const ref = decl && classOfDecl(decl);
14721
+ const schema = ref && findSdkModule(ref.platform, ref.module);
14722
+ if (!ref || !schema) return void 0;
14723
+ const tag = viewTag(ref.cls, schema, (m) => findSdkModule(ref.platform, m));
14724
+ for (const a of element.attributes.properties) {
14725
+ const name = ts.isJsxAttribute(a) ? a.name.getText() : void 0;
14726
+ const reason = name && tag.refused.get(name);
14727
+ if (reason) return {
14728
+ message: `<${ref.cls.name}> does not take ${name}: ${reason}.`,
14729
+ fix: `call it in setup code, on the view made with create={() => new ${ref.cls.name}(…)}`
14730
+ };
14731
+ }
14732
+ }
14733
+ const MISSING_ATTRIBUTE = /* @__PURE__ */ new Set([2322, 2769]);
14734
+ function nodeAt(sf, pos) {
14735
+ let node = sf;
14736
+ for (let inner = sf; inner;) {
14737
+ node = inner;
14738
+ inner = ts.forEachChild(node, (c) => c.getStart(sf) <= pos && pos < c.getEnd() ? c : void 0);
14739
+ }
14740
+ return node;
14741
+ }
13868
14742
  function importDiagnostics(sf, platform) {
13869
14743
  const shared = !platformOf(sf.fileName);
13870
14744
  const out = [];
@@ -14016,6 +14890,12 @@ function conformsByRoot(checker, impl, declared) {
14016
14890
  const typeOf = (p) => checker.getTypeOfSymbolAtLocation(p, p.valueDeclaration ?? p.declarations[0]);
14017
14891
  return checker.isTypeAssignableTo(root, checker.getReturnTypeOfSignature(d)) && i.parameters.every((p, k) => checker.isTypeAssignableTo(typeOf(d.parameters[k]), typeOf(p)));
14018
14892
  }
14893
+ function described(checker, t) {
14894
+ const [sig, ...more] = t.getCallSignatures();
14895
+ const elements = sig && !more.length ? elementsOf(sig.getReturnType()) : void 0;
14896
+ if (!sig || !elements) return checker.typeToString(t);
14897
+ return `(${sig.parameters.map((p) => `${p.name}: ${checker.typeToString(checker.getTypeOfSymbol(p))}`).join(", ")}) => ${elements.map((e) => checker.typeToString(e)).join(" & ")}`;
14898
+ }
14019
14899
  function conformanceErrors(lp) {
14020
14900
  const checker = lp.checker;
14021
14901
  const out = [];
@@ -14046,7 +14926,7 @@ function conformanceErrors(lp) {
14046
14926
  if (!decl || !declared) continue;
14047
14927
  const implType = checker.getTypeOfSymbolAtLocation(i, decl);
14048
14928
  const declType = checker.getTypeOfSymbolAtLocation(d, declared);
14049
- if (!checker.isTypeAssignableTo(implType, declType) && !conformsByRoot(checker, implType, declType)) out.push(at$2(decl, `${d.name} in ${implName} has type ${checker.typeToString(implType)}, which does not match ${checker.typeToString(declType)} declared in ${declName}`));
14929
+ if (!checker.isTypeAssignableTo(implType, declType) && !conformsByRoot(checker, implType, declType)) out.push(at$2(decl, `${d.name} in ${implName} has type ${described(checker, implType)}, which does not match ${checker.typeToString(declType)} declared in ${declName}`));
14050
14930
  }
14051
14931
  for (const extra of impl.values()) {
14052
14932
  const decl = extra.valueDeclaration ?? extra.declarations?.[0];
@@ -14310,11 +15190,7 @@ function inUntypedPlatformCode(lp, d, untyped) {
14310
15190
  if (d.code !== Codes.TypeScript || !d.file || d.start === void 0 || !untyped.length || platformOf(d.file)) return false;
14311
15191
  const sf = lp.program.getSourceFile(path.resolve(d.file));
14312
15192
  if (!sf) return false;
14313
- let node = sf;
14314
- for (let inner = sf; inner;) {
14315
- node = inner;
14316
- inner = ts.forEachChild(node, (c) => c.getStart(sf) <= d.start && d.start < c.getEnd() ? c : void 0);
14317
- }
15193
+ const node = nodeAt(sf, d.start);
14318
15194
  const stmt = sf.statements.find((s) => s.getStart(sf) <= d.start && d.start < s.getEnd());
14319
15195
  const p = (ts.isIdentifier(node) ? importedFrom(sf, node.text) : void 0) ?? branchPlatform(lp.checker, node) ?? (stmt ? platformScopes(lp.checker, sf).platforms.get(stmt) : void 0);
14320
15196
  return !!p && untyped.includes(p);
@@ -14332,6 +15208,179 @@ function importedFrom(sf, name) {
14332
15208
  }
14333
15209
  }
14334
15210
  //#endregion
15211
+ //#region ../compiler/src/ui/roots.ts
15212
+ const ROOT_VIEWS = {
15213
+ ios: {
15214
+ module: "UIKit",
15215
+ name: "UIView"
15216
+ },
15217
+ android: {
15218
+ module: "android.view",
15219
+ name: "View"
15220
+ }
15221
+ };
15222
+ const SLOT_VIEWS = {
15223
+ ios: {
15224
+ module: "UIKit",
15225
+ name: "UIView"
15226
+ },
15227
+ android: {
15228
+ module: "android.view",
15229
+ name: "ViewGroup"
15230
+ }
15231
+ };
15232
+ const sdkClassOf = (classes) => (decl) => {
15233
+ const sdk = sdkModuleOf(decl.getSourceFile());
15234
+ const found = sdk && classes[sdk.platform];
15235
+ return found && found.module === sdk.module && decl.name?.text === found.name ? sdk.platform : void 0;
15236
+ };
15237
+ function toolkitOf(root) {
15238
+ const toolkit = toolkitOfModule(root.module);
15239
+ return toolkit && TOOLKITS[toolkit].root === root.name ? toolkit : void 0;
15240
+ }
15241
+ const sdkRootView = sdkClassOf(ROOT_VIEWS);
15242
+ const sdkRoot = (decl) => {
15243
+ const builtin = builtinSdkModuleOf(decl.getSourceFile());
15244
+ const toolkit = builtin && toolkitOf({
15245
+ module: builtin,
15246
+ name: decl.name?.text ?? ""
15247
+ });
15248
+ return toolkit ? TOOLKITS[toolkit].platform : sdkRootView(decl);
15249
+ };
15250
+ const sdkSlot = sdkClassOf(SLOT_VIEWS);
15251
+ function returnShape(checker, fn, platform, rootOf) {
15252
+ const signature = checker.getSignatureFromDeclaration(fn);
15253
+ const declared = signature ? checker.getReturnTypeOfSignature(signature) : void 0;
15254
+ const promised = declared && promisedType(checker, declared);
15255
+ const viewOf = (t) => viewClass(checker, t, rootOf);
15256
+ const isView = (t) => {
15257
+ const found = viewOf(t);
15258
+ return found && (!platform || found.platform === platform) ? found.decl : void 0;
15259
+ };
15260
+ if (promised) return members(promised).some(isView) ? { kind: "promised" } : { kind: "value" };
15261
+ const returned = returnedExpressions(checker, fn, platform).map((e) => nativeTagType(checker, e) ?? checker.getTypeAtLocation(e));
15262
+ const types = (fn.body ? returned : declared ? [declared] : []).flatMap(members);
15263
+ const views = [];
15264
+ let other;
15265
+ let viewName = "";
15266
+ for (const t of types) {
15267
+ if (t.flags & ts.TypeFlags.Any || viewOf(t) && !isView(t)) continue;
15268
+ const cls = isView(t);
15269
+ if (cls) {
15270
+ views.push(cls);
15271
+ viewName ||= checker.typeToString(t);
15272
+ } else other ??= checker.typeToString(t);
15273
+ }
15274
+ if (!views.length) return { kind: "value" };
15275
+ if (other !== void 0) return {
15276
+ kind: "ambiguous",
15277
+ view: viewName,
15278
+ other
15279
+ };
15280
+ return {
15281
+ kind: "view",
15282
+ root: commonClass(checker, views)
15283
+ };
15284
+ }
15285
+ function classIdentity(checker, returned) {
15286
+ const decl = ancestors(checker, returned).find((c) => c.getSourceFile().isDeclarationFile) ?? returned;
15287
+ const sf = decl.getSourceFile();
15288
+ return {
15289
+ module: sdkModuleOf(sf)?.module ?? builtinSdkModuleOf(sf) ?? path.basename(sf.fileName, ".d.ts"),
15290
+ name: decl.name?.text ?? ""
15291
+ };
15292
+ }
15293
+ function members(t) {
15294
+ return t.isUnion() ? t.types.flatMap(members) : elementsOf(t) ?? [t];
15295
+ }
15296
+ function elementsOf(t) {
15297
+ if (!t.isIntersection()) return void 0;
15298
+ const declOf = (m) => m.getSymbol()?.declarations?.[0];
15299
+ const elements = t.types.filter((m) => {
15300
+ const decl = declOf(m);
15301
+ return !!decl && ts.isInterfaceDeclaration(decl) && !!toolkitElement(decl);
15302
+ });
15303
+ const views = t.types.filter((m) => !elements.includes(m)).every((m) => {
15304
+ const decl = declOf(m);
15305
+ return !!decl && ts.isClassDeclaration(decl) && !!sdkRootView(decl);
15306
+ });
15307
+ return elements.length && views ? elements : void 0;
15308
+ }
15309
+ function nativeTagType(checker, e) {
15310
+ let jsx = e;
15311
+ while (ts.isParenthesizedExpression(jsx)) jsx = jsx.expression;
15312
+ const tag = ts.isJsxElement(jsx) ? jsx.openingElement.tagName : ts.isJsxSelfClosingElement(jsx) ? jsx.tagName : void 0;
15313
+ const symbol = tag && checker.getSymbolAtLocation(tag);
15314
+ const target = symbol && symbol.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
15315
+ const decl = target?.declarations?.[0];
15316
+ return decl && ts.isClassDeclaration(decl) ? checker.getDeclaredTypeOfSymbol(target) : void 0;
15317
+ }
15318
+ function promisedType(checker, t) {
15319
+ const name = t.getSymbol()?.getName();
15320
+ if (name !== "Promise" && name !== "PromiseLike") return void 0;
15321
+ return checker.getTypeArguments(t)[0];
15322
+ }
15323
+ function viewClass(checker, t, rootOf) {
15324
+ const decl = t.getSymbol()?.declarations?.[0];
15325
+ if (decl && ts.isInterfaceDeclaration(decl)) return toolkitElement(decl);
15326
+ if (!decl || !ts.isClassDeclaration(decl)) return void 0;
15327
+ for (const c of ancestors(checker, decl)) {
15328
+ const platform = rootOf(c);
15329
+ if (platform) return {
15330
+ decl,
15331
+ platform
15332
+ };
15333
+ }
15334
+ }
15335
+ function toolkitElement(decl) {
15336
+ const sf = decl.getSourceFile();
15337
+ const name = toolkitOfModule(builtinSdkModuleOf(sf));
15338
+ const found = name && toolkit(name);
15339
+ if (!found || found.element !== decl.name.text) return void 0;
15340
+ const root = sf.statements.find((s) => ts.isClassDeclaration(s) && s.name?.text === found.root);
15341
+ return root && {
15342
+ decl: root,
15343
+ platform: found.platform
15344
+ };
15345
+ }
15346
+ function toolkitRootType(checker, t) {
15347
+ const [first] = elementsOf(t) ?? [t];
15348
+ const decl = first?.getSymbol()?.declarations?.[0];
15349
+ const root = decl && ts.isInterfaceDeclaration(decl) ? toolkitElement(decl) : void 0;
15350
+ return root?.decl.name && checker.getTypeAtLocation(root.decl.name);
15351
+ }
15352
+ function ancestors(checker, decl) {
15353
+ const out = [];
15354
+ for (let c = decl; c && !out.includes(c); c = baseClass(checker, c)) out.push(c);
15355
+ return out;
15356
+ }
15357
+ function baseClass(checker, c) {
15358
+ const symbol = c.name && checker.getSymbolAtLocation(c.name);
15359
+ if (!symbol) return void 0;
15360
+ const type = checker.getDeclaredTypeOfSymbol(symbol);
15361
+ const base = checker.getBaseTypes(type)[0]?.getSymbol()?.declarations?.[0];
15362
+ return base && ts.isClassDeclaration(base) ? base : void 0;
15363
+ }
15364
+ function commonClass(checker, classes) {
15365
+ const [first, ...rest] = classes;
15366
+ const others = rest.map((c) => ancestors(checker, c));
15367
+ return ancestors(checker, first).find((c) => others.every((a) => a.includes(c))) ?? first;
15368
+ }
15369
+ function returnedExpressions(checker, fn, platform) {
15370
+ if (!fn.body) return [];
15371
+ if (!ts.isBlock(fn.body)) return [fn.body];
15372
+ const out = [];
15373
+ const visit = (n) => {
15374
+ if (ts.isFunctionLike(n)) return;
15375
+ const branch = platform && branchPlatform(checker, n);
15376
+ if (branch && branch !== platform) return;
15377
+ if (ts.isReturnStatement(n) && n.expression) out.push(n.expression);
15378
+ ts.forEachChild(n, visit);
15379
+ };
15380
+ ts.forEachChild(fn.body, visit);
15381
+ return out;
15382
+ }
15383
+ //#endregion
14335
15384
  //#region ../compiler/src/ui/compose-api.ts
14336
15385
  const KINDS = {
14337
15386
  double: "Double",
@@ -14713,6 +15762,8 @@ function shownToolkit(node, checker, seen = /* @__PURE__ */ new Set()) {
14713
15762
  function bodyOf(fn, name, checker) {
14714
15763
  const { title, platform } = TOOLKITS[name];
14715
15764
  const refused = `a ${title} component returns its body: JSX of ${title}'s views, which the setup's last statement returns`;
15765
+ const native = nativeJsxIn(fn, checker);
15766
+ if (native) fail$2(native, Codes.NativeViewJsx, "JSX of native views is what a component returns: return it, as the last statement of the component");
14716
15767
  if (fn.body && !ts.isBlock(fn.body)) {
14717
15768
  if (jsxRoot(fn.body)) return fn.body;
14718
15769
  bodyFail(fn.body, refused);
@@ -14747,6 +15798,19 @@ function isUiForm(checker, call, name) {
14747
15798
  const decl = ts.isIdentifier(callee) ? symbolOf$1(checker, callee)?.declarations?.[0] : void 0;
14748
15799
  return !!decl && ts.isFunctionDeclaration(decl) && decl.name?.text === name && builtinSdkModuleOf(decl.getSourceFile()) === "lucent:ui";
14749
15800
  }
15801
+ function nativeJsxIn(fn, checker) {
15802
+ let found;
15803
+ const visit = (n) => {
15804
+ if (found || n !== fn && ts.isFunctionLike(n)) return;
15805
+ if ((ts.isJsxElement(n) || ts.isJsxSelfClosingElement(n)) && nativeTagType(checker, n)) {
15806
+ found = n;
15807
+ return;
15808
+ }
15809
+ ts.forEachChild(n, visit);
15810
+ };
15811
+ if (fn.body) visit(fn.body);
15812
+ return found;
15813
+ }
14750
15814
  const isBind = (checker, call) => isUiForm(checker, call, "bind");
14751
15815
  function inSetupCode(node, setup) {
14752
15816
  for (let n = node.parent; n; n = n.parent) if (ts.isFunctionLike(n)) return n === setup;
@@ -15651,6 +16715,7 @@ const LIBRARY = {
15651
16715
  },
15652
16716
  "lucent:android.appContext": NONE,
15653
16717
  "lucent:android.available": NONE,
16718
+ "lucent:android.errorOf": ALLOCATES,
15654
16719
  "lucent:ios.available": NONE,
15655
16720
  "lucent:ui.effect": {
15656
16721
  allocates: true,
@@ -16521,6 +17586,17 @@ var Collector = class Collector {
16521
17586
  return !!(decl && this.p.units.byNode.get(decl))?.generator;
16522
17587
  }
16523
17588
  jsx(e) {
17589
+ if (!ts.isJsxFragment(e) && nativeTagType(this.checker, e)) {
17590
+ const opening = ts.isJsxElement(e) ? e.openingElement : e;
17591
+ for (const a of opening.attributes.properties) {
17592
+ const value = ts.isJsxAttribute(a) ? a.initializer && ts.isJsxExpression(a.initializer) ? a.initializer.expression : void 0 : a.expression;
17593
+ if (value) this.expr(value);
17594
+ }
17595
+ for (const c of ts.isJsxElement(e) ? e.children : []) if (ts.isJsxExpression(c) && c.expression) this.expr(c.expression);
17596
+ else if (!ts.isJsxText(c)) this.expr(c);
17597
+ this.own("allocates", "yes", e, "makes native views");
17598
+ return this.made(e, "fresh");
17599
+ }
16524
17600
  if (!jsxToolkitOf(e, this.checker)) return this.unmodeled(e, ts.isJsxFragment(e) ? "a JSX fragment" : "a JSX element");
16525
17601
  this.own("allocates", "yes", e, "makes a toolkit's body");
16526
17602
  return this.made(e, "fresh");
@@ -17148,104 +18224,6 @@ function useOf$1(f, decl) {
17148
18224
  };
17149
18225
  }
17150
18226
  //#endregion
17151
- //#region ../compiler/src/sdk/declarations.ts
17152
- function classOfDecl(decl) {
17153
- const sdk = sdkModuleOf(decl.getSourceFile());
17154
- if (!sdk) return void 0;
17155
- const owner = ts.isClassDeclaration(decl) ? decl : decl.parent;
17156
- if (!owner || !ts.isClassDeclaration(owner) || !owner.name) return void 0;
17157
- const cls = findSdkType(sdk.platform, sdk.module, owner.name.text);
17158
- return cls?.kind === "class" ? {
17159
- ...sdk,
17160
- cls
17161
- } : void 0;
17162
- }
17163
- function sdkInterfacesOf(checker, decl) {
17164
- const out = [];
17165
- for (const h of decl.heritageClauses ?? []) {
17166
- if (h.token !== ts.SyntaxKind.ImplementsKeyword) continue;
17167
- for (const t of h.types) {
17168
- const d = checker.getTypeAtLocation(t).getSymbol()?.declarations?.find(ts.isClassDeclaration);
17169
- const ref = d ? classOfDecl(d) : void 0;
17170
- if (ref?.cls.interface) out.push(ref);
17171
- }
17172
- }
17173
- return out;
17174
- }
17175
- function requirementOf(checker, m) {
17176
- const cls = m.parent;
17177
- if (!ts.isClassLike(cls) || !ts.isIdentifier(m.name)) return void 0;
17178
- for (const protocol of sdkInterfacesOf(checker, cls)) {
17179
- const method = protocol.cls.methods?.find((x) => !x.static && x.name === m.name.text);
17180
- if (method) return {
17181
- protocol,
17182
- method,
17183
- main: !!(protocol.cls.mainActor || method.mainActor)
17184
- };
17185
- }
17186
- }
17187
- function schemaMethod(ref, decl) {
17188
- const inherited = inheritedFrom(ref, decl);
17189
- if (inherited) return {
17190
- ref: inherited.ref,
17191
- method: inherited.ref.cls.methods[inherited.index],
17192
- promise: false
17193
- };
17194
- const name = decl.name.text;
17195
- const index = decl.parent.members.filter((m) => ts.isMethodDeclaration(m) && m.name.text === name).indexOf(decl);
17196
- return (ref.cls.methods ?? []).flatMap((m) => [...m.name === name ? [{
17197
- ref,
17198
- method: m,
17199
- promise: false
17200
- }] : [], ...m.async && declaresPromise(ref.cls, m) && (m.async.name ?? m.name) === name ? [{
17201
- ref,
17202
- method: m,
17203
- promise: true
17204
- }] : []])[index];
17205
- }
17206
- function schemaProperty(ref, decl) {
17207
- const inherited = inheritedFrom(ref, decl);
17208
- if (inherited) return {
17209
- ref: inherited.ref,
17210
- property: inherited.ref.cls.properties[inherited.index]
17211
- };
17212
- const name = decl.name.text;
17213
- const isStatic = !!ts.getModifiers(decl)?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);
17214
- const property = ref.cls.properties?.find((p) => p.name === name && !!p.static === isStatic);
17215
- return property ? {
17216
- ref,
17217
- property
17218
- } : void 0;
17219
- }
17220
- function inheritedFrom(ref, decl) {
17221
- const tag = ts.getJSDocTags(decl).find((t) => `@${t.tagName.text}` === INHERITED_TAG);
17222
- if (!tag) return void 0;
17223
- const [owner, index] = (ts.getTextOfJSDocComment(tag.comment) ?? "").split(" ");
17224
- const dot = owner.lastIndexOf(".");
17225
- const module = owner.slice(0, dot);
17226
- const cls = findSdkType(ref.platform, module, owner.slice(dot + 1));
17227
- if (cls?.kind !== "class") throw new Error(`${owner}: no class for an inherited member`);
17228
- return {
17229
- ref: {
17230
- ...ref,
17231
- module,
17232
- cls
17233
- },
17234
- index: Number(index)
17235
- };
17236
- }
17237
- function schemaConstructor(ref, decl) {
17238
- return ref.cls.constructors[decl.parent.members.filter(ts.isConstructorDeclaration).indexOf(decl)];
17239
- }
17240
- function promiseForm(m) {
17241
- const { throws: _, ...rest } = m;
17242
- return {
17243
- ...rest,
17244
- params: m.params.slice(0, -1),
17245
- returns: m.async.returns
17246
- };
17247
- }
17248
- //#endregion
17249
18227
  //#region ../compiler/src/analysis/native.ts
17250
18228
  const NO_NATIVE = {
17251
18229
  use: () => void 0,
@@ -17270,6 +18248,7 @@ const COPIED$1 = /* @__PURE__ */ new Set([
17270
18248
  "copy-array",
17271
18249
  "copy-record",
17272
18250
  "copy-set",
18251
+ "copy-tuple",
17273
18252
  "copy-date"
17274
18253
  ]);
17275
18254
  function callbackOf$1(plan) {
@@ -17366,7 +18345,7 @@ function classMemberPlan(ref, decl, role) {
17366
18345
  return memberPlan(owner.platform, owner.module, owner.cls, promise ? promiseForm(method) : method, "call");
17367
18346
  }
17368
18347
  if (ts.isConstructorDeclaration(decl)) return memberPlan(ref.platform, ref.module, ref.cls, schemaConstructor(ref, decl), "new");
17369
- if (!ts.isPropertyDeclaration(decl) || !ts.isIdentifier(decl.name)) return void 0;
18348
+ if (!isSdkPropertyDecl(decl) || !ts.isIdentifier(decl.name)) return void 0;
17370
18349
  const found = schemaProperty(ref, decl);
17371
18350
  if (!found) return void 0;
17372
18351
  const { ref: owner, property } = found;
@@ -20034,10 +21013,12 @@ var Lowerer = class Lowerer {
20034
21013
  if (node.flags & ts.NodeFlags.OptionalChain) this.unsupported(node, "optional chains");
20035
21014
  const { operands, args } = this.operands();
20036
21015
  const place = host.place(node, operands);
21016
+ const assign = place.assign;
20037
21017
  return {
20038
21018
  type: place.type,
20039
21019
  read: () => this.planOf(place.get, args, spanOf(node)),
20040
- write: (v, span) => void this.planOf(place.set(v), [...args, v], span)
21020
+ write: (v, span) => void this.planOf(place.set(v), [...args, v], span),
21021
+ ...assign ? { assign: (v, span) => void this.planOf(assign(v, this.b.typeOf(v)), [...args, v], span) } : {}
20041
21022
  };
20042
21023
  }
20043
21024
  asserted(node) {
@@ -20406,11 +21387,14 @@ var Lowerer = class Lowerer {
20406
21387
  }
20407
21388
  conditional(node, hint) {
20408
21389
  const guard = this.host.platformGuard?.(node.condition);
20409
- const live = guard && guard.runs !== "nowhere" && (guard.runs === "elsewhere" || !guard.rest.length) ? guard.runs === "here" ? node.whenTrue : node.whenFalse : void 0;
21390
+ if (guard?.runs === "nowhere") {
21391
+ const typed = [node.whenTrue, node.whenFalse].find((e) => !(this.host.checker.getTypeAtLocation(e).flags & ts.TypeFlags.Any));
21392
+ return this.platformOnly(node, this.typeAt(typed ?? node));
21393
+ }
21394
+ const live = guard && (guard.runs === "elsewhere" || !guard.rest.length) ? guard.runs === "here" ? node.whenTrue : node.whenFalse : void 0;
20410
21395
  const own = this.typeAt(live ?? node);
20411
21396
  const promised = own.k === "promise" || own.k === "union" && own.ms.some((m) => m.k === "promise");
20412
21397
  const type = hint && !isVoidish(hint) && !promised ? hint : own;
20413
- if (guard?.runs === "nowhere") return this.platformOnly(node, own);
20414
21398
  if (live) return this.coerce(this.expr(live, type), type, live);
20415
21399
  const cond = guard ? this.all(guard.rest) : this.condition(node.condition);
20416
21400
  const branch = (e) => () => this.b.yield(this.coerce(this.expr(e, type), type, e), spanOf(e));
@@ -20690,6 +21674,11 @@ const BINARY_FORMS = {
20690
21674
  return value;
20691
21675
  }
20692
21676
  const target = lw.target(n.left);
21677
+ if (target.assign) {
21678
+ const value = lw.expr(n.right);
21679
+ target.assign(value, spanOf(n));
21680
+ return value;
21681
+ }
20693
21682
  const value = lw.expr(n.right, target.type);
20694
21683
  target.write(lw.coerce(value, target.type, n.right), spanOf(n));
20695
21684
  return value;
@@ -21330,6 +22319,8 @@ var Emitter = class {
21330
22319
  }
21331
22320
  aliases = /* @__PURE__ */ new Set();
21332
22321
  inlined = /* @__PURE__ */ new Set();
22322
+ temporaries = /* @__PURE__ */ new Map();
22323
+ current;
21333
22324
  definitions = /* @__PURE__ */ new Map();
21334
22325
  spellings() {
21335
22326
  const plain = /* @__PURE__ */ new Set();
@@ -21415,14 +22406,16 @@ var Emitter = class {
21415
22406
  this.suspended = true;
21416
22407
  }
21417
22408
  region(id) {
21418
- const saved = this.out;
22409
+ const [saved, savedRegion] = [this.out, this.current];
21419
22410
  const ops = this.fn.regions[id].ops;
21420
22411
  this.out = [];
22412
+ this.current = id;
21421
22413
  try {
21422
22414
  ops.forEach((op, i) => EMIT[op.kind](op, this, i, ops));
21423
22415
  return this.out;
21424
22416
  } finally {
21425
22417
  this.out = saved;
22418
+ this.current = savedRegion;
21426
22419
  }
21427
22420
  }
21428
22421
  branch(id, result) {
@@ -21454,6 +22447,16 @@ var Emitter = class {
21454
22447
  value(v) {
21455
22448
  return this.exprs.get(v);
21456
22449
  }
22450
+ taken(v) {
22451
+ const value = this.value(v);
22452
+ if ([
22453
+ "number",
22454
+ "boolean",
22455
+ "undefined",
22456
+ "null"
22457
+ ].includes(this.typeOf(v).k) || this.uses.get(v) !== 1 || this.temporaries.get(v) !== this.current) return value;
22458
+ return call$5("std::move", [value]);
22459
+ }
21457
22460
  place(p) {
21458
22461
  return this.places.get(p);
21459
22462
  }
@@ -21567,12 +22570,14 @@ var Emitter = class {
21567
22570
  const name = `v${v}_`;
21568
22571
  this.emit(op, varDecl(this.backend.cppType(this.fn.values[v].type), name, c));
21569
22572
  this.exprs.set(v, id(name));
22573
+ this.temporaries.set(v, this.current);
21570
22574
  } else if (effect) this.emit(op, exprStmt$4(cast$3("c", voidType, c)));
21571
22575
  }
21572
- bind(v, c) {
22576
+ bind(v, c, home) {
21573
22577
  if (!this.used(v)) return [];
21574
22578
  const name = `v${v}_`;
21575
22579
  this.exprs.set(v, id(name));
22580
+ this.temporaries.set(v, home);
21576
22581
  return [varDecl(this.backend.cppType(this.typeOf(v)), name, c)];
21577
22582
  }
21578
22583
  declareEmpty(op, v) {
@@ -21734,7 +22739,7 @@ const EMIT = {
21734
22739
  if (prev?.kind === "local" && prev.place === op.place) {
21735
22740
  const type = int ? type$5(INT_CPP[int]) : boxOf(e.backend.cppType(prev.type), prev.boxed);
21736
22741
  const style = prev.boxed ? { style: "construct" } : {};
21737
- const value = int ? e.stored(op.value, int) : e.value(op.value);
22742
+ const value = int ? e.stored(op.value, int) : e.taken(op.value);
21738
22743
  e.emit(op, varDecl(type, cppIdent(prev.name), value, style));
21739
22744
  return;
21740
22745
  }
@@ -21747,7 +22752,7 @@ const EMIT = {
21747
22752
  e.emit(op, exprStmt$4(assign$4(e.place(op.place), e.value(appended), "+=")));
21748
22753
  return;
21749
22754
  }
21750
- e.emit(op, exprStmt$4(assign$4(e.place(op.place), e.value(op.value))));
22755
+ e.emit(op, exprStmt$4(assign$4(e.place(op.place), e.taken(op.value))));
21751
22756
  },
21752
22757
  call: (op, e) => {
21753
22758
  const args = op.args.map((a) => e.value(a));
@@ -21813,7 +22818,7 @@ const EMIT = {
21813
22818
  const body = e.region(op.body);
21814
22819
  if (!op.catch) return [block$2(body)];
21815
22820
  const ex = `ex${op.catch.error}_`;
21816
- const error = e.bind(op.catch.error, call$5("lucent::currentError", [id(ex)]));
22821
+ const error = e.bind(op.catch.error, call$5("lucent::currentError", [id(ex)]), op.catch.region);
21817
22822
  const handler = e.region(op.catch.region);
21818
22823
  return [
21819
22824
  varDecl(type$5("std::exception_ptr"), ex),
@@ -21881,7 +22886,7 @@ const EMIT = {
21881
22886
  next: false
21882
22887
  };
21883
22888
  const body = (element, head = []) => {
21884
- const bound = e.bind(op.element, element);
22889
+ const bound = e.bind(op.element, element, op.body);
21885
22890
  const inner = e.inside(jump, op.body);
21886
22891
  return [
21887
22892
  ...head,
@@ -22139,6 +23144,7 @@ var Ctx = class {
22139
23144
  platform;
22140
23145
  frameworks = /* @__PURE__ */ new Set();
22141
23146
  pods = /* @__PURE__ */ new Set();
23147
+ swiftPackages = /* @__PURE__ */ new Set();
22142
23148
  javaClasses = /* @__PURE__ */ new Set();
22143
23149
  androidPermissions = /* @__PURE__ */ new Set();
22144
23150
  nativeUnits = /* @__PURE__ */ new Map();
@@ -22742,6 +23748,38 @@ function suspending(p, module) {
22742
23748
  function anyFor(name, bounds) {
22743
23749
  return bounds?.[name] === "non-null" ? type$3("Any") : nullable$1(type$3("Any"));
22744
23750
  }
23751
+ function boundType(ref) {
23752
+ const named = type$3(ref.name, ...(ref.args ?? []).map((a) => a === "*" ? star : boundType(a)));
23753
+ return ref.nullable ? nullable$1(named) : named;
23754
+ }
23755
+ function declaredTypeParams(use) {
23756
+ const classFacts = use.cls.kotlin;
23757
+ const memberFacts = use.member.kotlin;
23758
+ const classParams = use.cls.typeParams ?? [];
23759
+ const memberParams = "typeParams" in use.member ? use.member.typeParams ?? [] : [];
23760
+ const other = (f) => Object.keys(f?.upperBounds ?? {}).length > 0;
23761
+ if (!other(classFacts) && !other(memberFacts)) return {
23762
+ names: [],
23763
+ bounds: {}
23764
+ };
23765
+ const fromClass = use.instance || use.role === "new" ? classParams : [];
23766
+ const clash = memberParams.find((n) => fromClass.includes(n));
23767
+ if (clash) fail$2(use.node, Codes.UnsupportedCall, `${use.what}: its type parameter ${clash} shadows its class's, which a shim cannot declare twice`);
23768
+ const bounds = {};
23769
+ const bind = (names, f) => {
23770
+ for (const n of names) {
23771
+ const upper = f?.upperBounds?.[n];
23772
+ if (upper) bounds[n] = upper.map(boundType);
23773
+ else if (f?.bounds?.[n] === "non-null") bounds[n] = [type$3("Any")];
23774
+ }
23775
+ };
23776
+ bind(fromClass, classFacts);
23777
+ bind(memberParams, memberFacts);
23778
+ return {
23779
+ names: [...fromClass, ...memberParams],
23780
+ bounds
23781
+ };
23782
+ }
22745
23783
  function boundary(t) {
22746
23784
  const prim = primOf(t);
22747
23785
  return prim ? {
@@ -22767,6 +23805,7 @@ function kotlinType$1(use, t) {
22767
23805
  return of ? type$3(`kotlin.${of.kotlin}Array`) : type$3("kotlin.Array", kotlinType$1(use, t.of));
22768
23806
  }
22769
23807
  case "tparam": {
23808
+ if (declaredTypeParams(use).names.includes(t.name)) return type$3(t.name);
22770
23809
  const own = "typeParams" in use.member && use.member.typeParams?.includes(t.name);
22771
23810
  return anyFor(t.name, own ? use.member.kotlin?.bounds : use.cls.kotlin?.bounds);
22772
23811
  }
@@ -22802,7 +23841,8 @@ function kotlinShim(ctx, use) {
22802
23841
  memberName,
22803
23842
  use.given.map((g, i) => g ? use.wrapped[i] ? "f" : 1 : 0).join("")
22804
23843
  ].join("|");
22805
- const name = `${use.cls.name}_${use.role === "get" ? `get_${memberName}` : memberName}_${hashOf(key)}`;
23844
+ const accessor = use.role === "get" || use.role === "set" ? `${use.role}_` : "";
23845
+ const name = `${use.cls.name}_${accessor}${memberName}_${hashOf(key)}`;
22806
23846
  const shims = ctx.kotlinShims.get(use.module) ?? /* @__PURE__ */ new Map();
22807
23847
  ctx.kotlinShims.set(use.module, shims);
22808
23848
  const made = shims.get(name);
@@ -22821,6 +23861,7 @@ function kotlinShim(ctx, use) {
22821
23861
  const receiverType = (extension ? params[0] : void 0)?.type;
22822
23862
  if (use.instance) take("receiver", "receiver");
22823
23863
  else if (receiverType) take("receiver", primOf(receiverType) ? receiverType : "receiver");
23864
+ if (use.role === "set" && "type" in use.member) take("value", use.member.type);
22824
23865
  const sourceParams = extension ? params.slice(1) : params;
22825
23866
  const given = extension ? use.given.slice(1) : use.given;
22826
23867
  const wrapped = extension ? use.wrapped.slice(1) : use.wrapped;
@@ -22835,8 +23876,10 @@ function kotlinShim(ctx, use) {
22835
23876
  value: runs ? suspendingLambda(a, runs) : primOf(p.type) ? name$2(a) : call$3(name$2("cast"), [{ value: name$2(a) }])
22836
23877
  });
22837
23878
  });
22838
- const classArgs = (use.cls.typeParams ?? []).map((n) => anyFor(n, use.cls.kotlin?.bounds));
22839
- const memberArgs = ("typeParams" in use.member ? use.member.typeParams ?? [] : []).map((n) => anyFor(n, use.member.kotlin?.bounds));
23879
+ const declared = declaredTypeParams(use);
23880
+ const typeArg = (n, bounds) => declared.names.includes(n) ? type$3(n) : anyFor(n, bounds);
23881
+ const classArgs = (use.cls.typeParams ?? []).map((n) => typeArg(n, use.cls.kotlin?.bounds));
23882
+ const memberArgs = ("typeParams" in use.member ? use.member.typeParams ?? [] : []).map((n) => typeArg(n, use.member.kotlin?.bounds));
22840
23883
  const typeArgs = (list) => list.length ? list : void 0;
22841
23884
  const cast = (t) => call$3(name$2("cast"), [{ value: name$2("receiver") }], void 0, [t]);
22842
23885
  const pkg = use.module;
@@ -22851,7 +23894,7 @@ function kotlinShim(ctx, use) {
22851
23894
  const n = identifier(use, memberName);
22852
23895
  if (extension) imports.push(`${pkg}.${n}`);
22853
23896
  const reached = target ? member$5(target, n) : qualified(`${topLevel ? pkg : kotlinName(use.cls.native)}.${n}`);
22854
- return use.role === "get" ? reached : call$3(reached, args, void 0, typeArgs(memberArgs));
23897
+ return use.role === "get" || use.role === "set" ? reached : call$3(reached, args, void 0, typeArgs(memberArgs));
22855
23898
  })();
22856
23899
  let body;
22857
23900
  let ret;
@@ -22862,6 +23905,10 @@ function kotlinShim(ctx, use) {
22862
23905
  ret = type$3("AutoCloseable");
22863
23906
  retDescriptor = "Ljava/lang/AutoCloseable;";
22864
23907
  body = [ret$1(call$3(name$2("start"), [{ value: name$2("done") }], lambda$1([], [exprStmt$2(call)])))];
23908
+ } else if (use.role === "set") {
23909
+ const value = "type" in use.member && primOf(use.member.type);
23910
+ retDescriptor = "V";
23911
+ body = [assign$2(call, value ? name$2("value") : call$3(name$2("cast"), [{ value: name$2("value") }]))];
22865
23912
  } else if (isVoid$1(use.returns)) {
22866
23913
  retDescriptor = "V";
22867
23914
  body = [exprStmt$2(call)];
@@ -22879,6 +23926,10 @@ function kotlinShim(ctx, use) {
22879
23926
  k: "fun",
22880
23927
  annotations: ["JvmStatic"],
22881
23928
  modifiers: [],
23929
+ ...declared.names.length ? {
23930
+ typeParams: declared.names,
23931
+ bounds: declared.bounds
23932
+ } : {},
22882
23933
  name,
22883
23934
  params: shimParams,
22884
23935
  ...ret ? { ret } : {},
@@ -23592,7 +24643,7 @@ function toLucent(ctx, vt, lt, r) {
23592
24643
  case "string": return call$5(views("lucentString"), [r]);
23593
24644
  case "enum": return call$5(views("lucentString"), [dot(r, "value")]);
23594
24645
  case "array": {
23595
- const e = element(lt);
24646
+ const e = element$1(lt);
23596
24647
  return call$5(views("lucentArray"), [r, each(toLucent(ctx, vt.element, e, value))], [ctx.reg.cppType(e)]);
23597
24648
  }
23598
24649
  case "nullable": {
@@ -23628,7 +24679,7 @@ function assignRepr(ctx, target, vt, lt, src) {
23628
24679
  case "array": return [exprStmt$4(call$5(views("assignArray"), [
23629
24680
  target,
23630
24681
  src,
23631
- each((t, e) => assignRepr(ctx, t, vt.element, element(lt), e))
24682
+ each((t, e) => assignRepr(ctx, t, vt.element, element$1(lt), e))
23632
24683
  ]))];
23633
24684
  case "nullable": return [exprStmt$4(call$5(views("assignOpt"), [
23634
24685
  target,
@@ -23660,7 +24711,7 @@ function unwrapped(lt) {
23660
24711
  if (lt.k !== "opt") throw new Error(`expected an optional type (got ${lt.k})`);
23661
24712
  return lt.inner;
23662
24713
  }
23663
- function element(lt) {
24714
+ function element$1(lt) {
23664
24715
  if (lt.k !== "array") throw new Error(`expected an array type (got ${lt.k})`);
23665
24716
  return lt.e;
23666
24717
  }
@@ -24713,6 +25764,153 @@ const composeEmitter = {
24713
25764
  }
24714
25765
  };
24715
25766
  //#endregion
25767
+ //#region ../compiler/src/emit/native-jsx.ts
25768
+ function nativeJsx(em, node) {
25769
+ const setup = setupOf(em.ctx, node);
25770
+ if (!setup || !returnedBy(node, setup.fn)) fail$2(node, Codes.NativeViewJsx, "JSX of native views is what a component returns: return it, as the last statement of the component");
25771
+ const made = {
25772
+ statements: [],
25773
+ cleanup: [],
25774
+ captures: []
25775
+ };
25776
+ const root = element(em, node, made);
25777
+ made.statements.push(exprStmt$4(call$5(arrow$1(call$5("lucent::ui::mainGraph"), "onCleanup"), [lambda$2(made.captures, [], made.cleanup)])));
25778
+ return {
25779
+ c: statementExpr(made.statements, id(root)),
25780
+ t: setup.root
25781
+ };
25782
+ }
25783
+ const discarded = (c) => exprStmt$4(c.k === "call" ? c : cast$3("c", voidType, c));
25784
+ function returnedBy(node, fn) {
25785
+ let at = node;
25786
+ while (ts.isParenthesizedExpression(at.parent)) at = at.parent;
25787
+ const body = fn.body;
25788
+ const last = body && ts.isBlock(body) ? body.statements.at(-1) : void 0;
25789
+ return body === at || !!last && ts.isReturnStatement(last) && last.expression === at;
25790
+ }
25791
+ function refuseCopies(em, fn, value) {
25792
+ const props = fn.parameters[0] && em.checker.getSymbolAtLocation(fn.parameters[0].name);
25793
+ const body = fn.body && ts.isBlock(fn.body) ? fn.body : void 0;
25794
+ if (!props || !body) return;
25795
+ const visit = (n) => {
25796
+ if (ts.isFunctionLike(n)) return;
25797
+ const decl = (ts.isIdentifier(n) ? em.checker.getSymbolAtLocation(n) : void 0)?.valueDeclaration;
25798
+ const statement = decl?.parent?.parent;
25799
+ let read = decl && ts.isVariableDeclaration(decl) ? decl.initializer : void 0;
25800
+ while (read && ts.isParenthesizedExpression(read)) read = read.expression;
25801
+ let root = read;
25802
+ while (root && ts.isPropertyAccessExpression(root)) root = root.expression;
25803
+ if (read && read !== root && root && ts.isIdentifier(root) && em.checker.getSymbolAtLocation(root) === props && statement && ts.isVariableStatement(statement) && statement.parent === body) fail$2(n, Codes.NativeViewJsx, `\`${n.getText()}\` is ${read.getText()} as setup first read it: the attribute would never change`, `read ${read.getText()} in the attribute, which keeps it up to date`);
25804
+ ts.forEachChild(n, visit);
25805
+ };
25806
+ visit(value);
25807
+ }
25808
+ function element(em, node, made) {
25809
+ const setup = setupOf(em.ctx, node);
25810
+ let jsx = node;
25811
+ while (ts.isParenthesizedExpression(jsx)) jsx = jsx.expression;
25812
+ if (!ts.isJsxElement(jsx) && !ts.isJsxSelfClosingElement(jsx)) fail$2(node, Codes.NativeViewJsx, "a native view's children are elements of native views");
25813
+ const opening = ts.isJsxElement(jsx) ? jsx.openingElement : jsx;
25814
+ const tag = opening.tagName;
25815
+ const ref = sdkTagClass(em, tag);
25816
+ if (!ref) fail$2(tag, Codes.NativeViewJsx, `<${tag.getText()}> is no SDK view class: a native view's JSX is UIKit's or Android's views`);
25817
+ const at = tag;
25818
+ const schema = findSdkModule(ref.platform, ref.module);
25819
+ if (!schema) throw new Error(`${ref.module}: no schema for a class it declares`);
25820
+ const rules = viewTag(ref.cls, schema, (m) => findSdkModule(ref.platform, m));
25821
+ const owned = (o) => ({
25822
+ platform: ref.platform,
25823
+ module: o.schema.module,
25824
+ cls: o.cls
25825
+ });
25826
+ const lt = em.reg.lower(nativeTagType(em.checker, node), node);
25827
+ const view = em.ctx.fresh(`view_${ref.cls.name}`);
25828
+ const attributes = opening.attributes.properties;
25829
+ for (const a of attributes) if (!ts.isJsxAttribute(a)) fail$2(a, Codes.NativeViewJsx, "a native view's attributes are written one by one, not spread");
25830
+ const named = (name) => attributes.find((a) => ts.isJsxAttribute(a) && a.name.getText() === name);
25831
+ const valueOf = (a) => a.initializer && ts.isJsxExpression(a.initializer) ? a.initializer.expression : a.initializer;
25832
+ const create = named("create");
25833
+ const createdBy = create && valueOf(create);
25834
+ if (createdBy) {
25835
+ const f = em.ctx.fresh("create");
25836
+ made.statements.push(varDecl(auto$1, f, em.expr(createdBy).c), varDecl(auto$1, view, call$5(id(f), [])));
25837
+ } else {
25838
+ if (rules.construction.kind === "create") fail$2(tag, Codes.NativeViewJsx, rules.construction.reason);
25839
+ made.statements.push(varDecl(auto$1, view, viewNew(em, at, ref, rules.construction, lt).c));
25840
+ }
25841
+ const self = {
25842
+ c: id(view),
25843
+ t: lt
25844
+ };
25845
+ made.captures.push(view);
25846
+ for (const a of attributes) {
25847
+ const name = a.name.getText();
25848
+ if (name === "create") continue;
25849
+ const value = valueOf(a);
25850
+ const prop = rules.props.get(name);
25851
+ const event = rules.events.get(name);
25852
+ if (event) {
25853
+ if (!value) fail$2(a, Codes.NativeViewJsx, `${name} takes a function`);
25854
+ const owner = owned(event.owner);
25855
+ const handler = em.expr(value);
25856
+ if (event.event.kind === "listener") {
25857
+ const listened = listenerEvent(em, value, owner, event.event.setter, self, handler);
25858
+ made.statements.push(exprStmt$4(listened.add));
25859
+ made.cleanup.push(exprStmt$4(listened.remove));
25860
+ } else {
25861
+ const action = em.ctx.fresh("action");
25862
+ const control = controlEvent(em, value, owner, ref, event.event.register, event.event.value, self, handler);
25863
+ made.statements.push(varDecl(auto$1, action, control.add));
25864
+ made.cleanup.push(exprStmt$4(control.remove(id(action))));
25865
+ made.captures.push(action);
25866
+ }
25867
+ continue;
25868
+ }
25869
+ if (!prop) fail$2(a, Codes.NativeViewJsx, `<${ref.cls.name}> has no ${name}: what its declarations give is a writable property, a setter, an event, or children`);
25870
+ const owner = owned(prop.owner);
25871
+ const type = em.lt(a.name);
25872
+ const set = (v) => prop.prop.kind === "property" ? propertySetter(em, value ?? at, owner, prop.prop.member, self, type)(v.c) : setterCall(em, value ?? at, owner, prop.prop.overloads, self, v);
25873
+ if (!value) {
25874
+ made.statements.push(discarded(set({
25875
+ c: id("true"),
25876
+ t: T.boolean
25877
+ })));
25878
+ continue;
25879
+ }
25880
+ refuseCopies(em, setup.fn, value);
25881
+ const property = prop.prop.kind === "property";
25882
+ const get = em.thunk(value, {
25883
+ site: value,
25884
+ ...property ? { type } : {}
25885
+ });
25886
+ const got = !property && get.t.k === "fn" ? get.t.ret : type;
25887
+ const keep = lambda$2([view, {
25888
+ name: "lucent_get",
25889
+ init: get.c
25890
+ }], [], [varDecl(auto$1, "lucent_value", call$5(id("lucent_get"))), discarded(set({
25891
+ c: id("lucent_value"),
25892
+ t: got
25893
+ }))], { mutable: true });
25894
+ made.statements.push(exprStmt$4(call$5("lucent::ui::effect", [
25895
+ call$5("lucent::ui::mainGraph"),
25896
+ enterMount(em, value, keep),
25897
+ str$5(site(value))
25898
+ ])));
25899
+ }
25900
+ const children = ts.isJsxElement(jsx) ? jsx.children.filter((c) => !(ts.isJsxText(c) && c.containsOnlyTriviaWhiteSpaces)) : [];
25901
+ if (children.length && !rules.children) fail$2(children[0], Codes.NativeViewJsx, `<${ref.cls.name}> takes no children: its class declares no method inserting a view at an index`);
25902
+ children.forEach((c, index) => {
25903
+ if (!ts.isJsxElement(c) && !ts.isJsxSelfClosingElement(c)) fail$2(c, Codes.NativeViewJsx, "a native view's children are elements of native views");
25904
+ const child = element(em, c, made);
25905
+ const { rule, owner } = rules.children;
25906
+ made.statements.push(exprStmt$4(insertChild(em, c, owned(owner), rule.insert, self, {
25907
+ c: id(child),
25908
+ t: lt
25909
+ }, index)));
25910
+ });
25911
+ return view;
25912
+ }
25913
+ //#endregion
24716
25914
  //#region ../compiler/src/ui/source-members.ts
24717
25915
  const indexes = /* @__PURE__ */ new WeakMap();
24718
25916
  function indexOf$1(schema) {
@@ -25715,7 +26913,7 @@ function writable(node, found) {
25715
26913
  const refused = unsupportedReason(found.plan);
25716
26914
  if (refused) bodyFail(node, `\`${found.display}\` cannot be written in a SwiftUI body yet: ${refused}`);
25717
26915
  const since = found.plan.availability?.since;
25718
- if (typeof since === "string" && compareVersions(since, "15.1") > 0) bodyFail(node, `\`${found.display}\` needs iOS ${since} (apps run from iOS ${MIN_IOS}): a SwiftUI body writes what every supported iOS has, for now`);
26916
+ if (typeof since === "string" && compareVersions(since, oldestIos()) > 0) bodyFail(node, `\`${found.display}\` needs iOS ${since} (apps run from iOS ${oldestIos()}): a SwiftUI body writes what every supported iOS has, for now`);
25719
26917
  }
25720
26918
  function isNothing(e) {
25721
26919
  return e.kind === ts.SyntaxKind.NullKeyword || e.kind === ts.SyntaxKind.FalseKeyword || ts.isIdentifier(e) && e.text === "undefined";
@@ -26316,6 +27514,7 @@ function toolkitMember(em, node) {
26316
27514
  }
26317
27515
  const BODY_PLACE = "the body a component returns";
26318
27516
  function toolkitJsx(em, node) {
27517
+ if (nativeTagType(em.checker, node)) return nativeJsx(em, node);
26319
27518
  const toolkit = jsxToolkitOf(node, em.checker);
26320
27519
  const setup = setupOf(em.ctx, node);
26321
27520
  if (!toolkit) throw new Error("JSX in a file of no toolkit (the program refuses it)");
@@ -26841,10 +28040,10 @@ function mountUnit(ctx, s) {
26841
28040
  };
26842
28041
  const ns = `lucent_app::${s.module.ns}`;
26843
28042
  const where = str$5(`${path.basename(c.source.file)}:${c.source.line}`);
26844
- const id$10 = str$5(c.id);
28043
+ const id$14 = str$5(c.id);
26845
28044
  const view = (e, what) => exprStmt$4(call$5("lucent::ui::reportViewError", [
26846
28045
  e,
26847
- id$10,
28046
+ id$14,
26848
28047
  str$5(what),
26849
28048
  where
26850
28049
  ]));
@@ -27631,6 +28830,7 @@ function bareSwiftType(t) {
27631
28830
  case "id": return type$2("Any");
27632
28831
  case "array": return array$1(swiftType(t.of));
27633
28832
  case "record": return dictionary(type$2("String"), swiftType(t.of));
28833
+ case "fn": return blockFunction(t.params.map(swiftType), t.ret.k === "prim" && t.ret.name === "void" ? type$2("Void") : swiftType(t.ret));
27634
28834
  case "ref": {
27635
28835
  const info = sdkTypeInfo("ios", t.module, t.name);
27636
28836
  if (info?.kind === "struct") return type$2(info.native);
@@ -27675,6 +28875,14 @@ function fromObject(t, o) {
27675
28875
  case "record":
27676
28876
  if (bridges(t.of)) return cast$4(swiftType(t));
27677
28877
  return each(cast$4(dictionary(type$2("String"), type$2("AnyObject"))), "mapValues", fromObject(t.of, n("$0")));
28878
+ case "fn": return call$2(n("unsafeBitCast"), [{ value: o }, {
28879
+ label: "to",
28880
+ value: n(`(${printType$1(swiftType(t))}).self`)
28881
+ }]);
28882
+ case "tuple": {
28883
+ const items = cast$4(array$1(type$2("AnyObject")));
28884
+ return tupleLiteral(t.of.map((x, i) => fromObject(x, index(items, num$3(i)))));
28885
+ }
27678
28886
  case "ref": {
27679
28887
  const e = swiftEnum(t);
27680
28888
  if (e) return index(casesOf(e), member$4(cast$4(type$2("NSNumber")), "intValue"));
@@ -27703,6 +28911,11 @@ function toObject(t, v) {
27703
28911
  case "id": return as(v, "AnyObject");
27704
28912
  case "array": return as(bridges(t.of) ? v : each(v, "map", toObject(t.of, n("$0"))), "NSArray");
27705
28913
  case "record": return as(bridges(t.of) ? v : each(v, "mapValues", toObject(t.of, n("$0"))), "NSDictionary");
28914
+ case "fn": return call$2(n("unsafeBitCast"), [{ value: cast(v, "as", swiftType(t)) }, {
28915
+ label: "to",
28916
+ value: n("AnyObject.self")
28917
+ }]);
28918
+ case "tuple": return as(arrayLiteral(t.of.map((x, i) => as(toObject(x, member$4(v, String(i))), "AnyObject"))), "NSArray");
27706
28919
  case "ref": {
27707
28920
  const e = swiftEnum(t);
27708
28921
  if (e) return call$2(n("NSNumber"), [{
@@ -28150,7 +29363,10 @@ const REFUSAL_CODES = {
28150
29363
  function requirePlan(node, of, member, role, declared = member) {
28151
29364
  const plan = memberPlan(of.platform, of.module, of.cls, member, role);
28152
29365
  const why = explainRefusal(plan);
28153
- if (why) fail$2(node, plan.refused ? REFUSAL_CODES[plan.refused.rule] ?? Codes.UnsupportedCall : Codes.UnsupportedType, why);
29366
+ if (why) {
29367
+ if (plan.refused) fail$2(node, REFUSAL_CODES[plan.refused.rule] ?? Codes.UnsupportedCall, why);
29368
+ fail$2(node, Codes.UnsupportedType, why, WRAP_UNBOUND[of.platform]);
29369
+ }
28154
29370
  noteSdkUse(of.platform, of.module, of.cls, declared, plan);
28155
29371
  return plan;
28156
29372
  }
@@ -28398,6 +29614,10 @@ function toObjcExpr(t, c, owned, what = "a value") {
28398
29614
  return t.cf ? bridgeTo("CFArrayRef", arr) : arr;
28399
29615
  }
28400
29616
  case "set": return objc("toNSSet", eachElement(t.of));
29617
+ case "tuple": {
29618
+ const v = id("t_");
29619
+ return statementExpr([varDecl(auto$1, "t_", c)], call$5("lucent::objc::toNSArrayOf", t.of.map((x, i) => boxed(x, call$5("std::get", [v], [num$5(i)])))));
29620
+ }
28401
29621
  case "record": {
28402
29622
  const dict = objc("toNSDictionary", eachElement(t.of));
28403
29623
  return t.cf ? bridgeTo("CFDictionaryRef", dict) : dict;
@@ -28451,7 +29671,7 @@ function toObjc(em, arg, t, use, owned = false) {
28451
29671
  if (t.k === "id" || t.k === "tparam") return toObjcExpr(t, em.expr(arg).c, owned);
28452
29672
  if (t.k === "out") return outArg(em, arg, t, owned);
28453
29673
  const what = argumentWhat(em, arg);
28454
- if (sdkStruct(t)) {
29674
+ if (sdkStruct(t) || t.k === "tuple") {
28455
29675
  const declared = em.checker.getContextualType(arg);
28456
29676
  const lt = declared ? em.reg.lower(declared, arg) : em.lt(arg);
28457
29677
  return toObjcExpr(t, em.exprAs(arg, lt), owned, what);
@@ -28598,6 +29818,18 @@ function fromObjc(em, code, t, lt, what, owned = false) {
28598
29818
  c: objc("fromNSError", code, w),
28599
29819
  t: lt
28600
29820
  };
29821
+ case "tuple": {
29822
+ const tuple = elem(lt);
29823
+ if (tuple.k !== "tuple") throw new Error(`${what}: a tuple read as ${tuple.k}`);
29824
+ const items = t.of.map((x, i) => {
29825
+ const read = lambda$2(["&"], [param$5(type$5("id"), "e_")], [ret$3(fromObjcItem(em, x, tuple.es[i], what))], { ret: em.reg.cppType(tuple.es[i]) });
29826
+ return call$5(read, [send$1(id("a_"), "objectAtIndex:", [num$5(i)])]);
29827
+ });
29828
+ return {
29829
+ c: statementExpr([varDecl(objcPointer("NSArray"), "a_", cast$3("c", objcPointer("NSArray"), code))], construct(em.reg.cppType(tuple), items)),
29830
+ t: tuple
29831
+ };
29832
+ }
28601
29833
  default: throw new Error(`${what}: an Objective-C ${t.k} value its plan refuses`);
28602
29834
  }
28603
29835
  }
@@ -28770,7 +30002,8 @@ function jniArgument(em, ref, arg, t) {
28770
30002
  t: typed
28771
30003
  };
28772
30004
  }
28773
- case "tparam": return em.expr(arg);
30005
+ case "tparam":
30006
+ case "fn": return em.expr(arg);
28774
30007
  default: throw new Error(`${t.k} values, which plans refuse over JNI`);
28775
30008
  }
28776
30009
  }
@@ -28807,8 +30040,10 @@ function jniOf(em, arg, t, value) {
28807
30040
  }
28808
30041
  case "ref":
28809
30042
  if (value.t.k === "fn") return javaProxy(em, arg, value, t);
30043
+ if (eitherMembers(value.t)) return jniEither(em, arg, t, value);
28810
30044
  return jni("unwrap", value.c);
28811
30045
  case "tparam": return toJavaObject(arg, value);
30046
+ case "fn": return toKotlinFunction(em, arg, t, value);
28812
30047
  default: throw new Error(`${t.k} values, which plans refuse over JNI`);
28813
30048
  }
28814
30049
  }
@@ -28883,38 +30118,84 @@ function javaProxy(em, arg, f, t) {
28883
30118
  function proxyEntry(em, node, module, owner, m, fn, capture, call) {
28884
30119
  const params = m.params.map((p) => parseSdkType(p.type, module, m.typeParams ?? []));
28885
30120
  const n = Math.min(fn.params.length, params.length);
28886
- const what = `${owner}.${m.name}`;
28887
30121
  const cls = findSdkType("android", module, owner);
28888
- if (cls?.kind !== "class") throw new Error(`${what}: no class`);
30122
+ if (cls?.kind !== "class") throw new Error(`${owner}.${m.name}: no class`);
28889
30123
  const plan = requirePlan(node, {
28890
30124
  platform: "android",
28891
30125
  module,
28892
30126
  cls
28893
30127
  }, m, "implement");
28894
30128
  requireTaken(node, plan, plan.inputs, n);
28895
- const args = proxyArguments(em, node, params.slice(0, n), fn, what);
30129
+ const descriptor = m.descriptor ?? jniDescriptor(m.params.map((p) => p.type), m.returns, m.typeParams);
30130
+ const ret = parseSdkType(m.returns, module, m.typeParams ?? []);
30131
+ const what = `${owner}.${m.name}`;
30132
+ const suspend = !!m.kotlin?.suspend;
30133
+ const slots = descriptorSlots(descriptor);
30134
+ const result = unboxedSlot(ret, suspend ? void 0 : slots.ret);
30135
+ const valueLt = suspend && fn.ret.k === "promise" ? fn.ret.inner : fn.ret;
30136
+ const box = (r) => result ? jni("unboxValueClass", env, str$5(result.native), str$5(result.underlying), jni("unwrap", r)) : suspend && ret.k === "prim" && ret.name === "void" ? jni("unit", env) : boxJava(em, node, ret, r, what, valueLt);
30137
+ return proxyMethod(em, node, {
30138
+ key: `${m.java ?? m.name}${descriptor.slice(0, descriptor.indexOf(")") + 1)}`,
30139
+ params: params.slice(0, n),
30140
+ unboxed: params.slice(0, n).map((p, i) => unboxedSlot(p, slots.params[i])),
30141
+ box,
30142
+ queued: plan.delivery === "queued",
30143
+ ...suspend ? { continuation: params.length } : {},
30144
+ what,
30145
+ fn,
30146
+ capture,
30147
+ call
30148
+ });
30149
+ }
30150
+ function descriptorSlots(descriptor) {
30151
+ const slots = descriptor.match(/\[*(?:[ZBCSIJFDV]|L[^;]+;)/g) ?? [];
30152
+ return {
30153
+ params: slots.slice(0, -1),
30154
+ ret: slots.at(-1) ?? "V"
30155
+ };
30156
+ }
30157
+ function unboxedSlot(t, slot) {
30158
+ if (t.k !== "ref" || !slot) return void 0;
30159
+ const cls = findSdkType("android", t.module, t.name);
30160
+ if (cls?.kind !== "class" || !cls.kotlin?.value) return void 0;
30161
+ return slot === `L${cls.native};` ? void 0 : {
30162
+ native: cls.native,
30163
+ underlying: slot
30164
+ };
30165
+ }
30166
+ function proxyMethod(em, node, m) {
30167
+ const args = proxyArguments(em, node, m.params, m.fn, m.what, m.unboxed);
28896
30168
  const names = args.map((_, i) => `a${i}_`);
28897
30169
  const convert = args.map((a, i) => varDecl(auto$1, names[i], a));
28898
- const ret = parseSdkType(m.returns, module, m.typeParams ?? []);
28899
- const holder = typeof capture === "string" ? capture : capture.name;
28900
- const made = call(names.map(id));
30170
+ const holder = typeof m.capture === "string" ? m.capture : m.capture.name;
30171
+ const made = m.call(names.map(id));
28901
30172
  const jobject = type$5("jobject");
28902
30173
  const entry = callbackEntry(em, node);
28903
- const body = plan.delivery === "queued" ? [
30174
+ const resumed = (k) => {
30175
+ const resume = id("resume_");
30176
+ const boxValue = lambda$2([], [param$5(pointer(type$5("JNIEnv")), "env"), param$5(reference(constType(auto$1)), "v_")], [ret$3(m.box(id("v_")))], { ret: jobject });
30177
+ const run = lambda$2([
30178
+ holder,
30179
+ ...names,
30180
+ "resume_"
30181
+ ], [], [exprStmt$4(jni("resumeWithResult", resume, lambda$2(["&"], [], [ret$3(made)]), boxValue))]);
30182
+ const start = lambda$2([holder, ...names], [param$5(type$5("lucent::jni::Resume"), "resume_")], [exprStmt$4(entry.later(run))]);
30183
+ return [...convert, ret$3(jni("suspendedCall", env, jni("arg", env, id("args_"), num$5(k)), start))];
30184
+ };
30185
+ const body = m.continuation !== void 0 ? resumed(m.continuation) : m.queued ? [
28904
30186
  ...convert,
28905
30187
  exprStmt$4(entry.later(lambda$2([holder, ...names], [], [exprStmt$4(cast$3("c", voidType, made))]))),
28906
30188
  ret$3(nullptr)
28907
- ] : [...convert, ret$3(entry.now(lambda$2(["&"], [], [varDecl(auto$1, "r_", made), ret$3(boxJava(node, ret, id("r_"), what, fn.ret))], { ret: jobject })))];
28908
- const descriptor = m.descriptor ?? jniDescriptor(m.params.map((p) => p.type), m.returns, m.typeParams);
28909
- const key = `${m.java ?? m.name}${descriptor.slice(0, descriptor.indexOf(")") + 1)}`;
28910
- const method = lambda$2([capture], [param$5(pointer(type$5("JNIEnv")), "env"), param$5(type$5("jobjectArray"), "args_")], body, { ret: jobject });
28911
- return initList([str$5(key), method]);
30189
+ ] : [...convert, ret$3(entry.now(lambda$2(["&"], [], [varDecl(auto$1, "r_", made), ret$3(m.box(id("r_")))], { ret: jobject })))];
30190
+ const method = lambda$2([m.capture], [param$5(pointer(type$5("JNIEnv")), "env"), param$5(type$5("jobjectArray"), "args_")], body, { ret: jobject });
30191
+ return initList([str$5(m.key), method]);
28912
30192
  }
28913
- function proxyArguments(em, node, params, fn, what) {
30193
+ function proxyArguments(em, node, params, fn, what, unboxed = []) {
28914
30194
  return params.map((p, i) => {
28915
- const a = jni("arg", env, id("args_"), num$5(i));
28916
- if (p.k === "prim") return unboxedPrim(p, a);
28917
- return fromJni(em, a, p, fn.params[i], what, node).c;
30195
+ const arg = jni("arg", env, id("args_"), num$5(i));
30196
+ if (p.k === "prim") return unboxedPrim(p, arg);
30197
+ const v = unboxed[i];
30198
+ return fromJni(em, v ? jni("boxValueClass", env, str$5(v.native), str$5(v.underlying), arg) : arg, p, fn.params[i], what, node).c;
28918
30199
  });
28919
30200
  }
28920
30201
  function kotlinFunction(em, arg, f, runs, what, site) {
@@ -28928,7 +30209,7 @@ function kotlinFunction(em, arg, f, runs, what, site) {
28928
30209
  const ret = runs.returns;
28929
30210
  const result = () => {
28930
30211
  const r = id("r_");
28931
- if (ret.k === "tparam") return boxJava(arg, ret, r, what, fn.ret);
30212
+ if (ret.k === "tparam") return boxJava(em, arg, ret, r, what, fn.ret);
28932
30213
  if (ret.k === "ref") return envCall("NewLocalRef", toJavaObjectOf(em, ret, r, fn.ret, what));
28933
30214
  return toJavaObjectOf(em, ret, r, fn.ret, what);
28934
30215
  };
@@ -28938,6 +30219,94 @@ function kotlinFunction(em, arg, f, runs, what, site) {
28938
30219
  const key = `invoke(${"Ljava/lang/Object;".repeat(arity)})`;
28939
30220
  return statementExpr([varDecl(auto$1, "f_", f.c)], jni("proxyFor", env, javaClass(em, `kotlin/jvm/functions/Function${arity}`), call$5(dot(id("f_"), "identity")), initList([initList([str$5(key), method])]), str$5(site)));
28940
30221
  }
30222
+ function eitherMembers(t) {
30223
+ const inner = stripOpt(t);
30224
+ return inner.k === "union" && inner.ms.some((m) => m.k === "fn") ? inner.ms : void 0;
30225
+ }
30226
+ function jniEither(em, arg, t, value) {
30227
+ const jobject = type$5("jobject");
30228
+ const present = (v) => {
30229
+ const u = id("u_");
30230
+ const each = eitherMembers(v.t).map((m, i) => {
30231
+ const got = {
30232
+ c: call$5("std::get", [u], [num$5(i)]),
30233
+ t: m
30234
+ };
30235
+ return {
30236
+ test: binary$2(call$5(dot(u, "index")), "==", num$5(i)),
30237
+ c: staticCast(jobject, m.k === "fn" ? javaProxy(em, arg, got, t) : jni("unwrap", got.c))
30238
+ };
30239
+ });
30240
+ const chain = each.slice(0, -1).reduceRight((rest, e) => conditional$1(e.test, e.c, rest), each.at(-1).c);
30241
+ return statementExpr([varDecl(auto$1, "u_", v.c)], chain);
30242
+ };
30243
+ return value.t.k === "opt" ? whenPresent(value, present) : present(value);
30244
+ }
30245
+ function whenPresent(value, present) {
30246
+ if (value.t.k !== "opt") throw new Error(`an optional value that is a ${value.t.k}`);
30247
+ const jobject = type$5("jobject");
30248
+ const o = id("o_");
30249
+ return statementExpr([varDecl(auto$1, "o_", value.c)], conditional$1(call$5(dot(o, "has")), staticCast(jobject, present({
30250
+ c: call$5(dot(o, "get")),
30251
+ t: value.t.inner
30252
+ })), staticCast(jobject, nullptr)));
30253
+ }
30254
+ function toKotlinFunction(em, arg, t, value) {
30255
+ if (value.t.k === "null" || value.t.k === "undefined") return nullptr;
30256
+ if (value.t.k === "opt") return whenPresent(value, (v) => toKotlinFunction(em, arg, t, v));
30257
+ const fn = value.t;
30258
+ if (fn.k !== "fn") fail$2(arg, Codes.UnsupportedType, "pass a function");
30259
+ const what = argumentWhat(em, arg);
30260
+ const plan = kotlinFunctionConversion(t);
30261
+ if (plan.op !== "callback") throw new Error(`${what}: a Kotlin function its plan refuses`);
30262
+ const n = Math.min(fn.params.length, t.params.length);
30263
+ requireTaken(arg, { display: what }, plan.of.slice(0, -1), n);
30264
+ const ret = t.ret;
30265
+ const box = (r) => {
30266
+ if (ret.k === "tparam") return boxJava(em, arg, ret, r, what, fn.ret);
30267
+ if (ret.k === "ref") return envCall("NewLocalRef", toJavaObjectOf(em, ret, r, fn.ret, what));
30268
+ return toJavaObjectOf(em, ret, r, fn.ret, what);
30269
+ };
30270
+ const entry = proxyMethod(em, arg, {
30271
+ key: `invoke(${"Ljava/lang/Object;".repeat(t.params.length)})`,
30272
+ params: t.params.slice(0, n),
30273
+ box,
30274
+ queued: plan.delivery === "queued",
30275
+ what,
30276
+ fn,
30277
+ capture: "f_",
30278
+ call: (a) => call$5(id("f_"), a)
30279
+ });
30280
+ return statementExpr([varDecl(auto$1, "f_", value.c)], jni("proxyFor", env, javaClass(em, `kotlin/jvm/functions/Function${t.params.length}`), call$5(dot(id("f_"), "identity")), initList([entry])));
30281
+ }
30282
+ function fromKotlinFunction(em, code, t, lt, what, node) {
30283
+ const fn = stripOpt(lt);
30284
+ if (fn.k !== "fn") throw new Error(`${what}: a Kotlin function read as ${fn.k}`);
30285
+ const arity = t.params.length;
30286
+ const params = fn.params.map((p, i) => param$5(em.reg.cppType(p), `v${i}_`));
30287
+ const args = t.params.map((p, i) => i < params.length ? toJavaObjectOf(em, p, id(`v${i}_`), fn.params[i], what) : nullptr);
30288
+ const isVoid = t.ret.k === "prim" && t.ret.name === "void";
30289
+ const r = id("r_");
30290
+ const result = isVoid ? void 0 : t.ret.k === "prim" ? unboxedPrim(t.ret, r) : fromJni(em, r, t.ret, fn.ret, `${what}'s result`, node).c;
30291
+ const call = envCall("CallObjectMethod", jni("unwrap", id("f_")), id("id_"), ...args);
30292
+ const body = [
30293
+ varDecl(pointer(type$5("JNIEnv")), "env", jni("env")),
30294
+ varDecl(type$5("lucent::jni::LocalFrame"), "frame_", env, { style: "construct" }),
30295
+ varDecl(type$5("jclass"), "cls_", jni("findClass", javaClass(em, `kotlin/jvm/functions/Function${arity}`)), { static: true }),
30296
+ varDecl(auto$1, "id_", jni("method", id("cls_"), str$5("invoke"), javaDescriptor(em, `(${"Ljava/lang/Object;".repeat(arity)})Ljava/lang/Object;`)), { static: true }),
30297
+ varDecl(auto$1, "r_", call),
30298
+ exprStmt$4(jni("check", env)),
30299
+ ...result ? [ret$3(result)] : []
30300
+ ];
30301
+ const lambda = lambda$2([{
30302
+ name: "f_",
30303
+ init: jni("wrap", env, code, str$5(what))
30304
+ }], params, body, { ret: em.reg.cppRetType(fn.ret) });
30305
+ const value = construct(em.reg.cppType(fn), [lambda]);
30306
+ if (lt.k !== "opt") return value;
30307
+ const optional = em.reg.cppType(lt);
30308
+ return conditional$1(code, construct(optional, [value]), construct(optional, [id("lucent::null")]));
30309
+ }
28941
30310
  function extendsSdk(base, to) {
28942
30311
  for (let t = base; t;) {
28943
30312
  if (t.module === to.module && t.name === to.name) return true;
@@ -28984,7 +30353,7 @@ function javaObjectOfClass(em, e, to, node) {
28984
30353
  const o = id("o_");
28985
30354
  return statementExpr([varDecl(auto$1, "o_", e.c)], jni("proxyFor", jni("env"), javaClass(em, iface.native), call$5(dot(o, "get")), initList(entries)));
28986
30355
  }
28987
- function boxJava(node, t, c, what, lt) {
30356
+ function boxJava(em, node, t, c, what, lt) {
28988
30357
  if (t.k === "string") return jni("toJString", env, c);
28989
30358
  if (t.k === "tparam") {
28990
30359
  const inner = lt ? stripOpt(lt) : void 0;
@@ -28993,6 +30362,7 @@ function boxJava(node, t, c, what, lt) {
28993
30362
  if (inner?.k === "boolean" && lt.k !== "opt") return jni("boxBoolean", env, c);
28994
30363
  fail$2(node, Codes.UnsupportedType, `${what} returns a type parameter's value: Lucent functions return an SDK object, a string or a boolean there`);
28995
30364
  }
30365
+ if (t.k === "ref") return envCall("NewLocalRef", toJavaObjectOf(em, t, c, lt, what));
28996
30366
  if (t.k !== "prim") throw new Error(`${what}: a ${t.k} result its plan refuses`);
28997
30367
  return boxedForJava(t, c, `${what}'s result`);
28998
30368
  }
@@ -29264,6 +30634,10 @@ function fromJni(em, code, t, lt, what, node) {
29264
30634
  t: lt
29265
30635
  };
29266
30636
  case "tparam": return fromJavaObject(code, lt, what, node);
30637
+ case "fn": return {
30638
+ c: fromKotlinFunction(em, code, t, lt, what, node),
30639
+ t: lt
30640
+ };
29267
30641
  default: throw new Error(`unsupported Java result type ${t.k}`);
29268
30642
  }
29269
30643
  }
@@ -29290,14 +30664,14 @@ function fromJniList(em, code, t, lt, what, node) {
29290
30664
  function jniCall(em, opts) {
29291
30665
  const result = opts.ret.k === "prim" && opts.ret.name === "void";
29292
30666
  const out = fromJni(em, id("r_"), opts.ret, opts.lt, opts.what, opts.node);
29293
- const id$6 = id("id_");
30667
+ const id$7 = id("id_");
29294
30668
  const body = [
29295
30669
  varDecl(pointer(type$5("JNIEnv")), "env", jni("env")),
29296
30670
  ...opts.pre ?? [],
29297
30671
  varDecl(type$5("lucent::jni::LocalFrame"), "frame_", env, { style: "construct" }),
29298
30672
  varDecl(type$5("jclass"), "cls_", jni("findClass", javaClass(em, opts.cls.native)), { static: true }),
29299
30673
  varDecl(auto$1, "id_", jni(opts.lookup, id("cls_"), str$5(opts.name), javaDescriptor(em, opts.desc)), { static: true }),
29300
- result ? exprStmt$4(opts.access(id$6)) : varDecl(auto$1, "r_", opts.access(id$6)),
30674
+ result ? exprStmt$4(opts.access(id$7)) : varDecl(auto$1, "r_", opts.access(id$7)),
29301
30675
  exprStmt$4(jni("check", env)),
29302
30676
  ret$3(result ? id("lucent::undefined") : out.c)
29303
30677
  ];
@@ -29315,7 +30689,7 @@ function argsOf(node) {
29315
30689
  function needOf(platform, since) {
29316
30690
  if (typeof since !== (platform === "android" ? "number" : "string")) return void 0;
29317
30691
  const version = String(since);
29318
- return compareVersions(version, platform === "ios" ? "15.1" : String(24)) > 0 ? {
30692
+ return compareVersions(version, platform === "ios" ? oldestIos() : String(24)) > 0 ? {
29319
30693
  platform,
29320
30694
  version
29321
30695
  } : void 0;
@@ -29327,7 +30701,7 @@ function availableArgs(need) {
29327
30701
  function requireAvailable(em, node, ref, since, what) {
29328
30702
  const need = needOf(ref.platform, since);
29329
30703
  if (!need || guarded(em, node, need)) return;
29330
- fail$2(node, Codes.Unavailable, need.platform === "ios" ? `${what} needs iOS ${need.version} (apps run from iOS ${MIN_IOS}): use it under if (available("ios", ${availableArgs(need)}))` : `${what} needs API ${need.version} (apps run from API 24): use it under if (available("android", ${need.version})) or Build_VERSION.SDK_INT >= ${need.version}`);
30704
+ fail$2(node, Codes.Unavailable, need.platform === "ios" ? `${what} needs iOS ${need.version} (apps run from iOS ${oldestIos()}): use it under if (available("ios", ${availableArgs(need)}))` : `${what} needs API ${need.version} (apps run from API 24): use it under if (available("android", ${need.version})) or Build_VERSION.SDK_INT >= ${need.version}`);
29331
30705
  }
29332
30706
  const API_LEVEL = "jvm:android/os/Build$VERSION#SDK_INT:I";
29333
30707
  function apiLevelRead(em, e) {
@@ -29468,6 +30842,7 @@ function iosSuperInit(em, node, base, subclass) {
29468
30842
  if (!ref || !decl || !ts.isConstructorDeclaration(decl)) fail$2(node, Codes.UnsupportedCall, `${base.name} cannot be constructed`);
29469
30843
  const ctor = schemaConstructor(ref, decl);
29470
30844
  if (ctor.swift) fail$2(node, Codes.UnsupportedClassFeature, `${base.name}: Swift initializers cannot be inherited`);
30845
+ if (ctor.factory) fail$2(node, Codes.UnsupportedClassFeature, `${base.name}: ${ctor.selector} makes its own object (a class method Swift imports as an initializer), so a subclass cannot call it as super(…): call another of ${base.name}'s initializers`);
29471
30846
  const plan = requirePlan(node, ref, ctor, "new");
29472
30847
  requireAvailable(em, node, ref, ctor.since, `new ${base.name}(…)`);
29473
30848
  noteIncludes(em, ref);
@@ -29512,7 +30887,14 @@ function nativeNew(em, node, t) {
29512
30887
  noteIncludes(em, ref);
29513
30888
  if (ref.platform === "ios") {
29514
30889
  const a = args.map((x, i) => toObjc(em, x, params[i], plan));
29515
- const created = send(send$1(ref.cls.native, "alloc"), ctor.selector ?? "init", a);
30890
+ if (ctor.cFunction) {
30891
+ const made = cast$3("bridge_transfer", type$5("id"), call$5(ctor.cFunction.name, a));
30892
+ return {
30893
+ c: call$5("lucent::objc::wrap", [made, str$5(`new ${t.name}`)]),
30894
+ t
30895
+ };
30896
+ }
30897
+ const created = send(ctor.factory ? id(ref.cls.native) : send$1(ref.cls.native, "alloc"), ctor.selector ?? "init", a);
29516
30898
  return {
29517
30899
  c: call$5("lucent::objc::wrap", [created, str$5(`new ${t.name}`)]),
29518
30900
  t
@@ -29573,7 +30955,7 @@ function nativeStaticProperty(em, node) {
29573
30955
  }
29574
30956
  return;
29575
30957
  }
29576
- if (!ts.isPropertyDeclaration(decl)) return void 0;
30958
+ if (!isSdkPropertyDecl(decl)) return void 0;
29577
30959
  const ref = classOfDecl(decl);
29578
30960
  if (!ref || !ts.getModifiers(decl)?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) return void 0;
29579
30961
  const found = schemaProperty(ref, decl);
@@ -29626,7 +31008,7 @@ function nativeMember(em, obj, node) {
29626
31008
  if (obj.t.k === "native" && obj.t.module === "lucent:ios" && obj.t.name === "Out" && ts.isIdentifier(name) && name.text === "value") return outValue(em, obj, name.parent);
29627
31009
  const decl = resolved(em, name)?.valueDeclaration;
29628
31010
  const ref = decl ? classOfDecl(decl) : void 0;
29629
- if (!ref || !decl || !ts.isPropertyDeclaration(decl)) fail$2(node, Codes.UnsupportedSyntax, "methods of platform objects must be called directly");
31011
+ if (!ref || !decl || !isSdkPropertyDecl(decl)) fail$2(node, Codes.UnsupportedSyntax, "methods of platform objects must be called directly");
29630
31012
  const found = schemaProperty(ref, decl);
29631
31013
  return property$1(em, node, found.ref, found.property, obj);
29632
31014
  }
@@ -29659,6 +31041,7 @@ function property$1(em, node, ref, prop, obj) {
29659
31041
  const lt = declaredLt(em, ref.platform, t, node);
29660
31042
  if (ref.platform === "ios") {
29661
31043
  if (prop.global) return fromObjc(em, id(prop.global), t, lt, what);
31044
+ if (prop.cFunctions) return fromObjc(em, call$5(prop.cFunctions.getter, obj ? [cfReceiver(ref, obj)] : []), t, lt, what);
29662
31045
  return fromObjc(em, send(objcReceiver(ref, obj), prop.selector ?? prop.name, []), t, lt, what);
29663
31046
  }
29664
31047
  if (plan.backend === "kotlin-shim") return kotlinCall(em, {
@@ -29696,7 +31079,7 @@ function property$1(em, node, ref, prop, obj) {
29696
31079
  lookup: obj ? "field" : "staticField",
29697
31080
  name: prop.name,
29698
31081
  desc: sig,
29699
- access: (id$7) => obj ? envCall(`Get${kind}Field`, jni("unwrap", id("recv_")), id$7) : envCall(`GetStatic${kind}Field`, id("cls_"), id$7),
31082
+ access: (id$12) => obj ? envCall(`Get${kind}Field`, jni("unwrap", id("recv_")), id$12) : envCall(`GetStatic${kind}Field`, id("cls_"), id$12),
29700
31083
  ret: t,
29701
31084
  lt,
29702
31085
  what,
@@ -29764,7 +31147,13 @@ function iosCall(em, node, ref, m, obj, plan, superOf) {
29764
31147
  const a = argsOf(node).map((x, i) => toObjc(em, x, parseSdkType(m.params[i].type, ref.module, tps), plan));
29765
31148
  const throws = plan.error?.detail === "nserror-out";
29766
31149
  const selector = m.selector ?? m.name;
29767
- const code = superOf ? send(cast$3("c", objcPointer(superOf), call$5("lucent::objc::unwrap", [obj.c])), superSelector(selector), a, throws) : send(objcReceiver(ref, obj), selector, a, throws);
31150
+ const c = m.cFunction;
31151
+ const cArgs = c && obj && c.self !== void 0 ? [
31152
+ ...a.slice(0, c.self),
31153
+ cfReceiver(ref, obj),
31154
+ ...a.slice(c.self)
31155
+ ] : a;
31156
+ const code = c ? call$5(c.name, cArgs) : superOf ? send(cast$3("c", objcPointer(superOf), call$5("lucent::objc::unwrap", [obj.c])), superSelector(selector), a, throws) : send(objcReceiver(ref, obj), selector, a, throws);
29768
31157
  const ret = parseSdkType(m.returns, ref.module, tps);
29769
31158
  const what = `${ref.cls.name}.${m.name}()`;
29770
31159
  const lt = declaredLt(em, "ios", ret, node);
@@ -29773,6 +31162,9 @@ function iosCall(em, node, ref, m, obj, plan, superOf) {
29773
31162
  return fromObjc(em, code, ret, lt, what, owned);
29774
31163
  }
29775
31164
  const superSelector = (selector) => `lucentSuper_${selector}`;
31165
+ function cfReceiver(ref, obj) {
31166
+ return cast$3("bridge", type$5(ref.cls.native), call$5("lucent::objc::unwrap", [obj.c]));
31167
+ }
29776
31168
  function objcReceiver(ref, obj) {
29777
31169
  if (!obj) return id(ref.cls.native);
29778
31170
  const type = ref.cls.interface ? protocol(ref.cls.native) : objcPointer(ref.cls.native);
@@ -29789,32 +31181,44 @@ function nativeLvalue(em, target, obj) {
29789
31181
  }
29790
31182
  const decl = resolved(em, target.name)?.valueDeclaration;
29791
31183
  const declaring = decl ? classOfDecl(decl) : void 0;
29792
- if (!declaring || !decl || !ts.isPropertyDeclaration(decl)) return void 0;
31184
+ if (!declaring || !decl || !isSdkPropertyDecl(decl)) return void 0;
29793
31185
  const found = schemaProperty(declaring, decl);
29794
31186
  if (!found || !!found.property.static !== !obj) return void 0;
29795
31187
  const { ref, property: prop } = found;
29796
- const plan = requirePlan(target, ref, prop, "set");
31188
+ const type = em.lt(target);
31189
+ const set = propertySetter(em, target, ref, prop, obj, type);
29797
31190
  const get = property$1(em, target, ref, prop, obj);
31191
+ if (ref.platform !== "android" || !prop.setter) return {
31192
+ get: get.c,
31193
+ set,
31194
+ type
31195
+ };
31196
+ const assign = (v) => propertySetter(em, target, ref, prop, obj, v.t)(v.c);
31197
+ return {
31198
+ get: get.c,
31199
+ set,
31200
+ assign,
31201
+ type
31202
+ };
31203
+ }
31204
+ function propertySetter(em, site, ref, prop, obj, type) {
31205
+ const plan = requirePlan(site, ref, prop, "set");
29798
31206
  const t = parseSdkType(prop.type, ref.module);
29799
- const type = em.lt(target);
29800
31207
  if (prop.swift) {
29801
31208
  const what = `${ref.cls.name}.${prop.name}`;
29802
- const use = swiftUse(target, ref, prop, "set", [t], VOID, what, !obj);
29803
- return {
29804
- get: get.c,
29805
- set: (v) => swiftSet(em, use, obj, v),
29806
- type
29807
- };
31209
+ const use = swiftUse(site, ref, prop, "set", [t], VOID, what, !obj);
31210
+ return (v) => swiftSet(em, use, obj, v);
29808
31211
  }
29809
31212
  if (ref.platform === "ios") {
29810
31213
  const set = (value) => {
29811
31214
  const v = id("v_");
29812
- const one = (x) => t.k === "fn" ? objcBlock(em, target, x, type, t, plan) : toObjcExpr({
31215
+ const one = (x) => t.k === "fn" ? objcBlock(em, site, x, type, t, plan) : toObjcExpr({
29813
31216
  ...t,
29814
31217
  nullable: false
29815
31218
  }, x, false, `${ref.cls.name}.${prop.name}`);
29816
31219
  const conv = t.nullable ? ifPresent(v, one) : one(v);
29817
31220
  const held = varDecl(auto$1, "v_", value);
31221
+ if (prop.cFunctions?.setter) return statementExpr([held, exprStmt$4(call$5(prop.cFunctions.setter, [...obj ? [cfReceiver(ref, obj)] : [], conv]))], v);
29818
31222
  if (!prop.weak) return statementExpr([held, exprStmt$4(send(objcReceiver(ref, obj), prop.setter, [conv]))], v);
29819
31223
  const [r, o] = [id("r_"), id("o_")];
29820
31224
  const keep = call$5("objc_setAssociatedObject", [
@@ -29831,40 +31235,50 @@ function nativeLvalue(em, target, obj) {
29831
31235
  exprStmt$4(send(r, prop.setter, [o]))
29832
31236
  ], v);
29833
31237
  };
29834
- return {
29835
- get: get.c,
29836
- set,
29837
- type
29838
- };
31238
+ return set;
29839
31239
  }
29840
31240
  if (!prop.setter) throw new Error(`${plan.display}: a Java field write its plan refuses`);
29841
- const desc = ref.cls.methods?.find((m) => (m.java ?? m.name) === prop.setter && m.params.length === 1)?.descriptor ?? jniDescriptor([prop.type], "void");
31241
+ const what = `${ref.cls.name}.${prop.name}`;
31242
+ const shim = plan.backend === "kotlin-shim" ? kotlinShim(em.ctx, {
31243
+ node: site,
31244
+ module: ref.module,
31245
+ cls: ref.cls,
31246
+ role: "set",
31247
+ member: prop,
31248
+ instance: !!obj,
31249
+ given: [],
31250
+ wrapped: [],
31251
+ returns: VOID,
31252
+ what
31253
+ }) : void 0;
31254
+ const desc = shim?.descriptor ?? ref.cls.methods?.find((m) => (m.java ?? m.name) === prop.setter && m.params.length === 1)?.descriptor ?? jniDescriptor([prop.type], "void");
31255
+ const recv = obj ? [jni("unwrap", id("recv_"))] : [];
29842
31256
  const set = (value) => {
29843
31257
  const v = id("v_");
29844
- const converted = jniOf(em, target, t, {
31258
+ const converted = jniOf(em, site, t, jniValue(em, ref, site, t, {
29845
31259
  c: v,
29846
31260
  t: type
29847
- });
31261
+ }));
29848
31262
  const call = jniCall(em, {
29849
- node: target,
29850
- cls: ref.cls,
29851
- lookup: obj ? "method" : "staticMethod",
29852
- name: prop.setter,
31263
+ node: site,
31264
+ cls: shim ? {
31265
+ kind: "class",
31266
+ name: shim.name,
31267
+ native: shim.owner
31268
+ } : ref.cls,
31269
+ lookup: obj && !shim ? "method" : "staticMethod",
31270
+ name: shim?.name ?? prop.setter,
29853
31271
  desc,
29854
- access: (id$5) => envCall(`Call${obj ? "" : "Static"}VoidMethod`, obj ? jni("unwrap", id("recv_")) : id("cls_"), id$5, converted),
31272
+ access: (id$4) => shim ? envCall("CallStaticVoidMethod", id("cls_"), id$4, ...recv, converted) : envCall(`Call${obj ? "" : "Static"}VoidMethod`, recv[0] ?? id("cls_"), id$4, converted),
29855
31273
  ret: VOID,
29856
31274
  lt: T.undefined,
29857
- what: `${ref.cls.name}.${prop.name}`,
31275
+ what,
29858
31276
  pre: obj ? [varDecl(auto$1, "recv_", obj.c)] : []
29859
31277
  });
29860
31278
  return statementExpr([varDecl(auto$1, "v_", value), exprStmt$4(call.c)], v);
29861
31279
  };
29862
31280
  noteIncludes(em, ref);
29863
- return {
29864
- get: get.c,
29865
- set,
29866
- type
29867
- };
31281
+ return set;
29868
31282
  }
29869
31283
  function nativeFunctionCall(em, node) {
29870
31284
  if (!ts.isIdentifier(node.expression)) return void 0;
@@ -29883,17 +31297,17 @@ function nativeFunctionCall(em, node) {
29883
31297
  const ret = parseSdkType(f.returns, sdk.module);
29884
31298
  return fromObjc(em, call$5(name, a), ret, declaredLt(em, "ios", ret, node), `${name}()`, owned);
29885
31299
  }
29886
- function nativeConstant(em, id$8) {
29887
- const decl = resolved(em, id$8)?.valueDeclaration;
31300
+ function nativeConstant(em, id$13) {
31301
+ const decl = resolved(em, id$13)?.valueDeclaration;
29888
31302
  const sdk = decl && ts.isVariableDeclaration(decl) ? sdkModuleOf(decl.getSourceFile()) : void 0;
29889
31303
  if (!sdk) return void 0;
29890
- const c = findSdkModule(sdk.platform, sdk.module).constants?.find((x) => x.name === id$8.text);
29891
- if (!c) fail$2(id$8, Codes.UnsupportedSyntax, `${id$8.text} has no binding`);
29892
- requirePlan(id$8, sdk, c, "get");
31304
+ const c = findSdkModule(sdk.platform, sdk.module).constants?.find((x) => x.name === id$13.text);
31305
+ if (!c) fail$2(id$13, Codes.UnsupportedSyntax, `${id$13.text} has no binding`);
31306
+ requirePlan(id$13, sdk, c, "get");
29893
31307
  const ct = parseSdkType(c.type, sdk.module);
29894
- if (c.swift) return swiftCall(em, swiftUse(id$8, sdk, c, "get", [], ct, c.name, true), void 0, []);
31308
+ if (c.swift) return swiftCall(em, swiftUse(id$13, sdk, c, "get", [], ct, c.name, true), void 0, []);
29895
31309
  noteFramework(em, sdk.module);
29896
- return fromObjc(em, id(c.name), ct, declaredLt(em, "ios", ct, id$8), c.name);
31310
+ return fromObjc(em, id(c.name), ct, declaredLt(em, "ios", ct, id$13), c.name);
29897
31311
  }
29898
31312
  function noteFramework(em, module) {
29899
31313
  const schema = loadSdkModule("ios", module);
@@ -29907,6 +31321,7 @@ function linkModule(em, schema) {
29907
31321
  for (const f of schema.frameworks ?? []) em.ctx.frameworks.add(f);
29908
31322
  const artifact = schema.provenance?.artifact;
29909
31323
  if (artifact?.startsWith("pod:")) em.ctx.pods.add(artifact.slice(4).split("@")[0]);
31324
+ if (artifact?.startsWith("spm:")) em.ctx.swiftPackages.add(artifact.slice(4));
29910
31325
  }
29911
31326
  function androidCall(em, node, ref, m, obj, plan) {
29912
31327
  const tps = m.typeParams ?? [];
@@ -30080,6 +31495,12 @@ function nativeBuiltinCall(em, node) {
30080
31495
  c: call$5("lucent::jni::currentActivity"),
30081
31496
  t: em.lt(node)
30082
31497
  };
31498
+ case "lucent:android.errorOf":
31499
+ unit.include("lucent/platform/android.h");
31500
+ return {
31501
+ c: call$5("lucent::jni::errorOf", [em.exprAs(args[0], declaredArg(em, args[0]))]),
31502
+ t: T.error
31503
+ };
30083
31504
  case "lucent:android.startActivityForResult":
30084
31505
  case "lucent:android.requestPermissions": {
30085
31506
  unit.include("lucent/platform/android.h");
@@ -30156,7 +31577,7 @@ function kotlinCall(em, call) {
30156
31577
  lookup: "staticMethod",
30157
31578
  name: shim.name,
30158
31579
  desc: shim.descriptor,
30159
- access: (id$4) => envCall(`CallStatic${kind}Method`, id("cls_"), id$4, ...recv, ...a),
31580
+ access: (id$6) => envCall(`CallStatic${kind}Method`, id("cls_"), id$6, ...recv, ...a),
30160
31581
  ret: returns,
30161
31582
  lt: call.lt ?? declaredLt(em, "android", returns, node),
30162
31583
  what,
@@ -30239,6 +31660,200 @@ function nativeInstanceOf(em, node) {
30239
31660
  t: T.boolean
30240
31661
  };
30241
31662
  }
31663
+ function sdkTagClass(em, tag) {
31664
+ return ts.isIdentifier(tag) || ts.isPropertyAccessExpression(tag) ? sdkClassNamed(em, tag) : void 0;
31665
+ }
31666
+ function viewNew(em, site, ref, construction, lt) {
31667
+ const owner = findSdkType(ref.platform, construction.module, construction.owner);
31668
+ const declaring = owner?.kind === "class" ? {
31669
+ ...ref,
31670
+ module: construction.module,
31671
+ cls: owner
31672
+ } : ref;
31673
+ const what = `<${ref.cls.name}>`;
31674
+ requireMain(em, site, ref);
31675
+ requirePlan(site, declaring, construction.ctor, "new");
31676
+ requireAvailable(em, site, ref, ref.cls.since, ref.cls.name);
31677
+ requireAvailable(em, site, ref, construction.ctor.since, what);
31678
+ if (construction.ctor.swift) fail$2(site, Codes.NativeViewJsx, `${ref.cls.name} is made through Swift: make it with create={() => new ${ref.cls.name}(…)}`);
31679
+ noteIncludes(em, ref);
31680
+ if (ref.platform === "ios") {
31681
+ const alloc = send$1(ref.cls.native, "alloc");
31682
+ const frame = construction.kind === "frame" ? [id("CGRectZero")] : [];
31683
+ const made = send(alloc, construction.ctor.selector ?? "init", frame);
31684
+ return {
31685
+ c: call$5("lucent::objc::wrap", [made, str$5(what)]),
31686
+ t: lt
31687
+ };
31688
+ }
31689
+ const self = {
31690
+ k: "ref",
31691
+ module: ref.module,
31692
+ name: ref.cls.name,
31693
+ nullable: false
31694
+ };
31695
+ const desc = construction.ctor.descriptor ?? jniDescriptor(construction.ctor.params.map((p) => p.type), "void");
31696
+ return jniCall(em, {
31697
+ node: site,
31698
+ cls: ref.cls,
31699
+ lookup: "method",
31700
+ name: "<init>",
31701
+ desc,
31702
+ access: (id$10) => envCall("NewObject", id("cls_"), id$10, jni("unwrap", id("context_"))),
31703
+ ret: self,
31704
+ lt,
31705
+ what,
31706
+ pre: [varDecl(auto$1, "context_", jni("viewContext"))]
31707
+ });
31708
+ }
31709
+ function takes(t, lt) {
31710
+ const v = stripOpt(lt);
31711
+ switch (t.k) {
31712
+ case "string": return v.k === "string";
31713
+ case "prim": return t.name === "boolean" || t.name === "bool" ? v.k === "boolean" : isWideInteger(t.name) ? v.k === "bigint" : v.k === "number";
31714
+ default: return ![
31715
+ "string",
31716
+ "boolean",
31717
+ "number",
31718
+ "bigint"
31719
+ ].includes(v.k);
31720
+ }
31721
+ }
31722
+ function jniValue(em, ref, site, t, value) {
31723
+ const as = (lt) => ({
31724
+ c: em.coerce(value, lt, site),
31725
+ t: lt
31726
+ });
31727
+ switch (t.k) {
31728
+ case "prim": return as(primLt(t));
31729
+ case "string": return as(t.nullable ? unionOf([T.string, T.null]) : T.string);
31730
+ case "array": {
31731
+ const lt = declaredLt(em, ref.platform, {
31732
+ ...t,
31733
+ nullable: false
31734
+ }, site);
31735
+ return as(t.nullable ? unionOf([lt, T.null]) : lt);
31736
+ }
31737
+ case "ref": {
31738
+ if (value.t.k === "fn" || eitherMembers(value.t)) return value;
31739
+ const lt = {
31740
+ k: "native",
31741
+ platform: ref.platform,
31742
+ module: t.module,
31743
+ name: t.name
31744
+ };
31745
+ return as(t.nullable ? unionOf([lt, T.null]) : lt);
31746
+ }
31747
+ default: return value;
31748
+ }
31749
+ }
31750
+ function setterCall(em, site, ref, overloads, obj, value) {
31751
+ const method = overloads.find((m) => takes(parseSdkType(m.params[0].type, ref.module), value.t)) ?? overloads[0];
31752
+ const t = parseSdkType(method.params[0].type, ref.module);
31753
+ const what = `${ref.cls.name}.${method.name}`;
31754
+ requirePlan(site, ref, method, "call");
31755
+ requireMain(em, site, ref, method);
31756
+ requireAvailable(em, site, ref, method.since, what);
31757
+ noteIncludes(em, ref);
31758
+ return jniCall(em, {
31759
+ node: site,
31760
+ cls: ref.cls,
31761
+ lookup: "method",
31762
+ name: method.java ?? method.name,
31763
+ desc: method.descriptor ?? jniDescriptor([method.params[0].type], "void"),
31764
+ access: (id$11) => envCall("CallVoidMethod", jni("unwrap", id("recv_")), id$11, jniOf(em, site, t, jniValue(em, ref, site, t, value))),
31765
+ ret: VOID,
31766
+ lt: T.undefined,
31767
+ what,
31768
+ pre: [varDecl(auto$1, "recv_", obj.c)]
31769
+ }).c;
31770
+ }
31771
+ function insertChild(em, site, ref, method, parent, child, index) {
31772
+ const what = `${ref.cls.name}.${method.selector ?? method.name}`;
31773
+ const childType = parseSdkType(method.params[0].type, ref.module);
31774
+ requirePlan(site, ref, method, "call");
31775
+ requireMain(em, site, ref, method);
31776
+ requireAvailable(em, site, ref, method.since, what);
31777
+ noteIncludes(em, ref);
31778
+ if (ref.platform === "ios") return send(objcReceiver(ref, parent), method.selector, [toObjcExpr({
31779
+ ...childType,
31780
+ nullable: false
31781
+ }, child.c, false, what), num$5(index)]);
31782
+ return jniCall(em, {
31783
+ node: site,
31784
+ cls: ref.cls,
31785
+ lookup: "method",
31786
+ name: method.java ?? method.name,
31787
+ desc: method.descriptor ?? jniDescriptor(method.params.map((p) => p.type), "void"),
31788
+ access: (id$8) => envCall("CallVoidMethod", jni("unwrap", id("recv_")), id$8, jni("unwrap", id("child_")), staticCast(type$5("jint"), num$5(index))),
31789
+ ret: VOID,
31790
+ lt: T.undefined,
31791
+ what,
31792
+ pre: [varDecl(auto$1, "recv_", parent.c), varDecl(auto$1, "child_", child.c)]
31793
+ }).c;
31794
+ }
31795
+ function listenerEvent(em, site, ref, setter, obj, handler) {
31796
+ const listener = parseSdkType(setter.params[0].type, ref.module);
31797
+ if (listener.k !== "ref") throw new Error(`${setter.name}: its listener is no class`);
31798
+ const what = `${ref.cls.name}.${setter.name}`;
31799
+ requirePlan(site, ref, setter, "call");
31800
+ requireMain(em, site, ref, setter);
31801
+ requireAvailable(em, site, ref, setter.since, what);
31802
+ noteIncludes(em, ref);
31803
+ const call = (given) => jniCall(em, {
31804
+ node: site,
31805
+ cls: ref.cls,
31806
+ lookup: "method",
31807
+ name: setter.java ?? setter.name,
31808
+ desc: setter.descriptor ?? jniDescriptor([setter.params[0].type], "void"),
31809
+ access: (id$5) => envCall("CallVoidMethod", jni("unwrap", id("recv_")), id$5, given),
31810
+ ret: VOID,
31811
+ lt: T.undefined,
31812
+ what,
31813
+ pre: [varDecl(auto$1, "recv_", obj.c)]
31814
+ }).c;
31815
+ return {
31816
+ add: call(javaProxy(em, site, handler, {
31817
+ ...listener,
31818
+ nullable: false
31819
+ })),
31820
+ remove: call(id("nullptr"))
31821
+ };
31822
+ }
31823
+ function controlEvent(em, site, ref, tag, register, value, obj, handler) {
31824
+ const what = `${ref.cls.name}.${register.selector}`;
31825
+ const fn = {
31826
+ k: "fn",
31827
+ params: [{
31828
+ k: "ref",
31829
+ module: tag.module,
31830
+ name: tag.cls.name,
31831
+ nullable: false
31832
+ }],
31833
+ ret: VOID,
31834
+ escaping: true,
31835
+ main: true,
31836
+ nullable: false
31837
+ };
31838
+ requirePlan(site, ref, register, "call");
31839
+ requireAvailable(em, site, ref, register.since, what);
31840
+ noteIncludes(em, ref);
31841
+ em.ctx.nativeUnit(em.opts.module).include("lucent/platform/ios_ui.h");
31842
+ const block = objcBlock(em, site, handler.c, handler.t, fn, { display: what });
31843
+ const control = call$5("lucent::objc::unwrap", [obj.c]);
31844
+ return {
31845
+ add: call$5("lucent::objc::addControlAction", [
31846
+ control,
31847
+ num$5(value),
31848
+ block
31849
+ ]),
31850
+ remove: (action) => call$5("lucent::objc::removeControlAction", [
31851
+ control,
31852
+ action,
31853
+ num$5(value)
31854
+ ])
31855
+ };
31856
+ }
30242
31857
  //#endregion
30243
31858
  //#region ../compiler/src/emit/extensions.ts
30244
31859
  function handleNew(em, node, t) {
@@ -31500,6 +33115,7 @@ var FnEmitter = class {
31500
33115
  const il = this.intLocal(target);
31501
33116
  if (il) return staticCast(type$5("double"), assign$4(id(il.cpp), this.toKind(value, il.int, node)));
31502
33117
  const lv = this.lvalue(target);
33118
+ if (lv.assign) return lv.assign(value);
31503
33119
  const v = this.coerce(value, lv.type, node);
31504
33120
  if (lv.direct) return assign$4(lv.direct, v);
31505
33121
  return lv.set(v);
@@ -31633,7 +33249,8 @@ var FnEmitter = class {
31633
33249
  lvalueType(target) {
31634
33250
  try {
31635
33251
  if (ts.isArrayLiteralExpression(target)) return void 0;
31636
- return this.lvalue(target).type;
33252
+ const lv = this.lvalue(target);
33253
+ return lv.assign ? void 0 : lv.type;
31637
33254
  } catch {
31638
33255
  return;
31639
33256
  }
@@ -33041,7 +34658,7 @@ function leafHost(ctx, opts) {
33041
34658
  place: (target, operands) => {
33042
34659
  const lv = new LeafEmitter(ctx, opts, target, operands).lvalue(target);
33043
34660
  const name = nameOf$2(target);
33044
- const { direct, set } = lv;
34661
+ const { direct, set, assign } = lv;
33045
34662
  if (!direct && !set) throw new IrUnsupported(target, "a place that cannot be written");
33046
34663
  return {
33047
34664
  type: lv.type,
@@ -33054,7 +34671,15 @@ function leafHost(ctx, opts) {
33054
34671
  name: `${name} =`,
33055
34672
  code: direct ? assign$4(direct, operand(v)) : set(operand(v)),
33056
34673
  type: T.void
33057
- })
34674
+ }),
34675
+ ...assign ? { assign: (v, from) => ({
34676
+ name: `${name} =`,
34677
+ code: assign({
34678
+ c: operand(v),
34679
+ t: from
34680
+ }),
34681
+ type: T.void
34682
+ }) } : {}
33058
34683
  };
33059
34684
  }
33060
34685
  };
@@ -38262,7 +39887,7 @@ function emitProgram(lp, target = lp.platform ?? "all", components = /* @__PURE_
38262
39887
  decls: [
38263
39888
  { k: "pragmaOnce" },
38264
39889
  include("lucent/lucent.h", true),
38265
- ...lp.modules.some((m) => /["']lucent:ui["']/.test(m.sourceFile.text)) ? [include("lucent/view.h", true)] : [],
39890
+ ...setups.size || lp.modules.some((m) => /["']lucent:ui["']/.test(m.sourceFile.text)) ? [include("lucent/view.h", true)] : [],
38266
39891
  ...shielded([...readers.decls.length ? [
38267
39892
  app(types),
38268
39893
  namespace("lucent", readers.decls),
@@ -38332,6 +39957,7 @@ function emitProgram(lp, target = lp.platform ?? "all", components = /* @__PURE_
38332
39957
  warnings: ctx.warnings,
38333
39958
  frameworks: [...ctx.frameworks].sort(),
38334
39959
  pods: [...ctx.pods].sort(),
39960
+ swiftPackages: [...ctx.swiftPackages].sort(),
38335
39961
  java,
38336
39962
  javaKeep: [...ctx.javaClasses].sort(),
38337
39963
  kotlin: new Map([...kotlinFiles(ctx), ...toolkitFiles(ctx, "compose")]),
@@ -40403,21 +42029,21 @@ function attributes(from, names) {
40403
42029
  return Object.fromEntries(names.filter((n) => from[n] !== void 0).map((n) => [`android:${n}`, String(from[n])]));
40404
42030
  }
40405
42031
  function componentElement(c) {
40406
- const named = (tag) => (name) => element$1(tag, { "android:name": name });
40407
- const children = [...(c.intentFilters ?? []).map((f) => element$1("intent-filter", {}, [
42032
+ const named = (tag) => (name) => element$2(tag, { "android:name": name });
42033
+ const children = [...(c.intentFilters ?? []).map((f) => element$2("intent-filter", {}, [
40408
42034
  ...f.actions.map(named("action")),
40409
42035
  ...(f.categories ?? []).map(named("category")),
40410
- ...(f.data ?? []).map((d) => element$1("data", attributes(d, DATA_ATTRIBUTES)))
40411
- ])), ...Object.entries(c.metaData ?? {}).map(([name, value]) => element$1("meta-data", {
42036
+ ...(f.data ?? []).map((d) => element$2("data", attributes(d, DATA_ATTRIBUTES)))
42037
+ ])), ...Object.entries(c.metaData ?? {}).map(([name, value]) => element$2("meta-data", {
40412
42038
  "android:name": name,
40413
42039
  "android:value": value
40414
42040
  }))];
40415
- return element$1(c.kind, attributes(c, COMPONENT_ATTRIBUTES), children.length ? children : void 0);
42041
+ return element$2(c.kind, attributes(c, COMPONENT_ATTRIBUTES), children.length ? children : void 0);
40416
42042
  }
40417
42043
  function androidManifest(permissions, components = []) {
40418
42044
  return printDocument({
40419
42045
  comment: "Generated by Lucent. Do not edit.",
40420
- root: element$1("manifest", { "xmlns:android": "http://schemas.android.com/apk/res/android" }, [...permissions.map((p) => element$1("uses-permission", { "android:name": p })), element$1("application", {}, [...RUNTIME_COMPONENTS, ...components].map(componentElement))])
42046
+ root: element$2("manifest", { "xmlns:android": "http://schemas.android.com/apk/res/android" }, [...permissions.map((p) => element$2("uses-permission", { "android:name": p })), element$2("application", {}, [...RUNTIME_COMPONENTS, ...components].map(componentElement))])
40421
42047
  });
40422
42048
  }
40423
42049
  function consumerRules(classes) {
@@ -40433,6 +42059,27 @@ function jsxToolkits() {
40433
42059
  return Object.fromEntries(Object.keys(TOOLKITS).map((name) => [TOOLKITS[name].platform, name]));
40434
42060
  }
40435
42061
  //#endregion
42062
+ //#region ../compiler/src/ui/view-coverage.ts
42063
+ function viewCoverage(schema, moduleOf) {
42064
+ if (!fabricRequested()) return void 0;
42065
+ const find = (module, name) => module === schema.module ? schema.types.find((t) => t.name === name) : moduleOf(module)?.types.find((t) => t.name === name);
42066
+ return schema.types.filter((t) => t.kind === "class" && !t.interface && isViewClass(t, schema, find)).map((cls) => {
42067
+ const rules = viewRules(cls, schema, find);
42068
+ const explained = (x) => ({
42069
+ name: x.name,
42070
+ explanation: x.explanation
42071
+ });
42072
+ return {
42073
+ view: cls.name,
42074
+ made: viewConstruction(cls, schema, find).kind,
42075
+ props: rules.props.map(explained),
42076
+ events: rules.events.map(explained),
42077
+ ...rules.children ? { children: rules.children.explanation } : {},
42078
+ leftOut: rules.refused
42079
+ };
42080
+ });
42081
+ }
42082
+ //#endregion
40436
42083
  //#region ../compiler/src/ui/android.ts
40437
42084
  const JAVA = "android/src/main/java/dev/lucent";
40438
42085
  const DESCRIPTORS_HEADER = "android/include/react/renderer/components/lucentnative/ComponentDescriptors.h";
@@ -40580,8 +42227,8 @@ function writeNativePackage(result, outDir, options = {}) {
40580
42227
  resources: inPackage(native?.ios.resources ?? []),
40581
42228
  resourceBundles: Object.entries(native?.ios.resourceBundles ?? {}).map(([name, paths]) => [name, inPackage(paths)]),
40582
42229
  vendoredFrameworks: inPackage(native?.ios.vendoredFrameworks ?? []),
40583
- swiftPackages: Object.entries(native?.ios.swiftPackages ?? {}),
40584
- deploymentTarget: native?.ios.deploymentTarget?.value
42230
+ swiftPackages: [...Object.entries(native?.ios.swiftPackages ?? {}), ...appSwiftPackages(result.swiftPackages ?? [], options.app?.swiftPackages ?? [])],
42231
+ deploymentTarget: highestVersion([native?.ios.deploymentTarget?.value, options.app?.deploymentTarget])
40585
42232
  }));
40586
42233
  const gradle = path.join(outDir, "android/build.gradle");
40587
42234
  want.set(gradle, options.androidDeferred ? deferredLibraryGradle(options.native) : libraryBuildGradle(want.get(gradle).toString(), options.native, !!result.kotlin?.size, result.compose ? [...result.kotlin].filter(([f]) => f.startsWith("dev/lucent/compose/")).map(([, t]) => t) : []));
@@ -40651,6 +42298,21 @@ function writeWhole(file, content) {
40651
42298
  fs.writeFileSync(tmp, content);
40652
42299
  fs.renameSync(tmp, file);
40653
42300
  }
42301
+ function appSwiftPackages(used, pins) {
42302
+ return pins.filter((p) => used.some((u) => u.slice(0, u.lastIndexOf("@")) === p.identity)).map((p) => [p.location, {
42303
+ requirement: p.version ? {
42304
+ kind: "exactVersion",
42305
+ version: p.version
42306
+ } : {
42307
+ kind: "revision",
42308
+ revision: p.revision
42309
+ },
42310
+ products: p.products
42311
+ }]);
42312
+ }
42313
+ function highestVersion(versions) {
42314
+ return versions.filter((v) => !!v).sort(compareVersions).at(-1);
42315
+ }
40654
42316
  //#endregion
40655
42317
  //#region ../compiler/src/sdk/modules.ts
40656
42318
  const composing = (platform) => platform === "android" && fabricRequested();
@@ -40739,6 +42401,7 @@ function compileWith(files, options) {
40739
42401
  if (target === "ios") {
40740
42402
  out.frameworks = result.frameworks;
40741
42403
  out.pods = result.pods;
42404
+ out.swiftPackages = result.swiftPackages;
40742
42405
  }
40743
42406
  if (target === "android") {
40744
42407
  out.java = result.java;
@@ -40848,4 +42511,4 @@ function report(diagnostics) {
40848
42511
  return diagnostics.map(formatDiagnostic).join("\n");
40849
42512
  }
40850
42513
  //#endregion
40851
- export { sdkSchemaEntry as $, findLucentFiles as A, diffModule as B, bindExtensions as C, LUCENT_EXTENSION as D, identityScript as E, moduleNamespace as F, cachedModules as G, displayName as H, extensionDts as I, forgetLoadedSdks as J, cachedSchema as K, sdkDts as L, platformOf as M, projectFiles as N, coreJsPath as O, usesPlatforms as P, sdkNames as Q, coverage as R, inNativePackage as S, RUNTIME_ABI as T, symbolKey as U, diffSymbols as V, podsSearchPaths as W, sdkAvailable as X, prefetch as Y, sdkModuleArtifacts as Z, VIEW_CONTRACT_VERSION as _, report as a, PACKAGE_FIELDS as b, sdkModules as c, isUpToDate as d, sdkSourceModule as et, runtimeDir as f, libraryBuildGradle as g, toolkitsFrom as h, projectExtensions as i, moduleNameOf as j, coreTypesPath as k, deferredLibraryGradle as l, jsxToolkits as m, compile as n, sdkDeclarations as o, writeNativePackage as p, extractionCount as q, compileDirectory as r, sdkModule as s, checkSources as t, formatDiagnostic as tt, inputsKey as u, resolveNative as v, forgetExtensionHeaders as w, fileHashes as x, EXTENSION_FIELDS as y, compareArtifacts as z };
42514
+ export { sdkNames as $, coreTypesPath as A, compareArtifacts as B, inNativePackage as C, identityScript as D, RUNTIME_ABI as E, usesPlatforms as F, podsSearchPaths as G, diffSymbols as H, moduleNamespace as I, extractionCount as J, cachedModules as K, extensionDts as L, moduleNameOf as M, platformOf as N, LUCENT_EXTENSION as O, projectFiles as P, sdkModuleArtifacts as Q, sdkDts as R, fileHashes as S, forgetExtensionHeaders as T, displayName as U, diffModule as V, symbolKey as W, prefetch as X, forgetLoadedSdks as Y, sdkAvailable as Z, libraryBuildGradle as _, report as a, EXTENSION_FIELDS as b, sdkModules as c, isUpToDate as d, sdkSchemaEntry as et, runtimeDir as f, toolkitsFrom as g, jsxToolkits as h, projectExtensions as i, formatDiagnostic as it, findLucentFiles as j, coreJsPath as k, deferredLibraryGradle as l, viewCoverage as m, compile as n, cacheRoot as nt, sdkDeclarations as o, writeNativePackage as p, cachedSchema as q, compileDirectory as r, hash$2 as rt, sdkModule as s, checkSources as t, sdkSourceModule as tt, inputsKey as u, VIEW_CONTRACT_VERSION as v, bindExtensions as w, PACKAGE_FIELDS as x, resolveNative as y, coverage as z };