static.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. const equalFn = (a, b) => a === b;
  2. const ERROR = Symbol("error");
  3. const UNOWNED = {
  4. context: null,
  5. owner: null
  6. };
  7. let Owner = null;
  8. function createRoot(fn, detachedOwner) {
  9. detachedOwner && (Owner = detachedOwner);
  10. const owner = Owner,
  11. root = fn.length === 0 ? UNOWNED : {
  12. context: null,
  13. owner
  14. };
  15. Owner = root;
  16. let result;
  17. try {
  18. result = fn(() => {});
  19. } catch (err) {
  20. const fns = lookup(Owner, ERROR);
  21. if (!fns) throw err;
  22. fns.forEach(f => f(err));
  23. } finally {
  24. Owner = owner;
  25. }
  26. return result;
  27. }
  28. function createSignal(value) {
  29. return [() => value, v => value = v];
  30. }
  31. function createComputed(fn, value) {
  32. Owner = {
  33. owner: Owner,
  34. context: null
  35. };
  36. fn(value);
  37. Owner = Owner.owner;
  38. }
  39. const createRenderEffect = createComputed;
  40. function createEffect(fn, value) {}
  41. function createMemo(fn, value) {
  42. Owner = {
  43. owner: Owner,
  44. context: null
  45. };
  46. const v = fn(value);
  47. Owner = Owner.owner;
  48. return () => v;
  49. }
  50. function createDeferred(source) {
  51. return source;
  52. }
  53. function createSelector(source, fn) {
  54. return k => fn(k, source());
  55. }
  56. function batch(fn) {
  57. return fn();
  58. }
  59. const untrack = batch;
  60. function on(deps, fn, options = {}) {
  61. let isArray = Array.isArray(deps);
  62. let defer = options.defer;
  63. return () => {
  64. if (defer) return undefined;
  65. let value;
  66. if (isArray) {
  67. value = [];
  68. for (let i = 0; i < deps.length; i++) value.push(deps[i]());
  69. } else value = deps();
  70. return fn(value, undefined);
  71. };
  72. }
  73. function onMount(fn) {}
  74. function onCleanup(fn) {}
  75. function onError(fn) {
  76. if (Owner === null) console.warn("error handlers created outside a `createRoot` or `render` will never be run");else if (Owner.context === null) Owner.context = {
  77. [ERROR]: [fn]
  78. };else if (!Owner.context[ERROR]) Owner.context[ERROR] = [fn];else Owner.context[ERROR].push(fn);
  79. }
  80. function getListener() {
  81. return null;
  82. }
  83. function createContext(defaultValue) {
  84. const id = Symbol("context");
  85. return {
  86. id,
  87. Provider: createProvider(id),
  88. defaultValue
  89. };
  90. }
  91. function useContext(context) {
  92. return lookup(Owner, context.id) || context.defaultValue;
  93. }
  94. function getOwner() {
  95. return Owner;
  96. }
  97. function children(fn) {
  98. return createMemo(() => resolveChildren(fn()));
  99. }
  100. function runWithOwner(o, fn) {
  101. const prev = Owner;
  102. Owner = o;
  103. try {
  104. return fn();
  105. } finally {
  106. Owner = prev;
  107. }
  108. }
  109. function lookup(owner, key) {
  110. return owner && (owner.context && owner.context[key] || owner.owner && lookup(owner.owner, key));
  111. }
  112. function resolveChildren(children) {
  113. if (typeof children === "function" && !children.length) return resolveChildren(children());
  114. if (Array.isArray(children)) {
  115. const results = [];
  116. for (let i = 0; i < children.length; i++) {
  117. let result = resolveChildren(children[i]);
  118. Array.isArray(result) ? results.push.apply(results, result) : results.push(result);
  119. }
  120. return results;
  121. }
  122. return children;
  123. }
  124. function createProvider(id) {
  125. return function provider(props) {
  126. return createMemo(() => {
  127. Owner.context = {
  128. [id]: props.value
  129. };
  130. return children(() => props.children);
  131. });
  132. };
  133. }
  134. function requestCallback(fn, options) {
  135. return {
  136. id: 0,
  137. fn: () => {},
  138. startTime: 0,
  139. expirationTime: 0
  140. };
  141. }
  142. const $RAW = Symbol("state-raw");
  143. function isWrappable(obj) {
  144. return obj != null && typeof obj === "object" && (obj.__proto__ === Object.prototype || Array.isArray(obj));
  145. }
  146. function unwrap(item) {
  147. return item;
  148. }
  149. function setProperty(state, property, value, force) {
  150. if (!force && state[property] === value) return;
  151. if (value === undefined) {
  152. delete state[property];
  153. } else state[property] = value;
  154. }
  155. function mergeState(state, value, force) {
  156. const keys = Object.keys(value);
  157. for (let i = 0; i < keys.length; i += 1) {
  158. const key = keys[i];
  159. setProperty(state, key, value[key], force);
  160. }
  161. }
  162. function updatePath(current, path, traversed = []) {
  163. let part,
  164. next = current;
  165. if (path.length > 1) {
  166. part = path.shift();
  167. const partType = typeof part,
  168. isArray = Array.isArray(current);
  169. if (Array.isArray(part)) {
  170. for (let i = 0; i < part.length; i++) {
  171. updatePath(current, [part[i]].concat(path), [part[i]].concat(traversed));
  172. }
  173. return;
  174. } else if (isArray && partType === "function") {
  175. for (let i = 0; i < current.length; i++) {
  176. if (part(current[i], i)) updatePath(current, [i].concat(path), [i].concat(traversed));
  177. }
  178. return;
  179. } else if (isArray && partType === "object") {
  180. const {
  181. from = 0,
  182. to = current.length - 1,
  183. by = 1
  184. } = part;
  185. for (let i = from; i <= to; i += by) {
  186. updatePath(current, [i].concat(path), [i].concat(traversed));
  187. }
  188. return;
  189. } else if (path.length > 1) {
  190. updatePath(current[part], path, [part].concat(traversed));
  191. return;
  192. }
  193. next = current[part];
  194. traversed = [part].concat(traversed);
  195. }
  196. let value = path[0];
  197. if (typeof value === "function") {
  198. value = value(next, traversed);
  199. if (value === next) return;
  200. }
  201. if (part === undefined && value == undefined) return;
  202. if (part === undefined || isWrappable(next) && isWrappable(value) && !Array.isArray(value)) {
  203. mergeState(next, value);
  204. } else setProperty(current, part, value);
  205. }
  206. function createState(state) {
  207. function setState(...args) {
  208. updatePath(state, args);
  209. }
  210. return [state, setState];
  211. }
  212. function reconcile(value, options = {}) {
  213. return state => {
  214. if (!isWrappable(state)) return value;
  215. const targetKeys = Object.keys(value);
  216. for (let i = 0, len = targetKeys.length; i < len; i++) {
  217. const key = targetKeys[i];
  218. setProperty(state, key, value[key]);
  219. }
  220. const previousKeys = Object.keys(state);
  221. for (let i = 0, len = previousKeys.length; i < len; i++) {
  222. if (value[previousKeys[i]] === undefined) setProperty(state, previousKeys[i], undefined);
  223. }
  224. };
  225. }
  226. function produce(fn) {
  227. return state => {
  228. if (isWrappable(state)) fn(state);
  229. return state;
  230. };
  231. }
  232. function mapArray(list, mapFn, options = {}) {
  233. const items = list();
  234. let s = [];
  235. if (items.length) {
  236. for (let i = 0, len = items.length; i < len; i++) s.push(mapFn(items[i], () => i));
  237. } else if (options.fallback) s = [options.fallback()];
  238. return () => s;
  239. }
  240. function resolveSSRNode(node) {
  241. const t = typeof node;
  242. if (t === "string") return node;
  243. if (node == null || t === "boolean") return "";
  244. if (Array.isArray(node)) return node.map(resolveSSRNode).join("");
  245. if (t === "object") return resolveSSRNode(node.t);
  246. if (t === "function") return resolveSSRNode(node());
  247. return String(node);
  248. }
  249. const sharedConfig = {};
  250. function setHydrateContext(context) {
  251. sharedConfig.context = context;
  252. }
  253. function nextHydrateContext() {
  254. return sharedConfig.context ? { ...sharedConfig.context,
  255. id: `${sharedConfig.context.id}${sharedConfig.context.count++}.`,
  256. count: 0
  257. } : undefined;
  258. }
  259. function createComponent(Comp, props) {
  260. if (sharedConfig.context) {
  261. const c = sharedConfig.context;
  262. setHydrateContext(nextHydrateContext());
  263. const r = Comp(props);
  264. setHydrateContext(c);
  265. return r;
  266. }
  267. return Comp(props);
  268. }
  269. function mergeProps(...sources) {
  270. const target = {};
  271. for (let i = 0; i < sources.length; i++) {
  272. const descriptors = Object.getOwnPropertyDescriptors(sources[i]);
  273. Object.defineProperties(target, descriptors);
  274. }
  275. return target;
  276. }
  277. function splitProps(props, ...keys) {
  278. const descriptors = Object.getOwnPropertyDescriptors(props),
  279. split = k => {
  280. const clone = {};
  281. for (let i = 0; i < k.length; i++) {
  282. const key = k[i];
  283. if (descriptors[key]) {
  284. Object.defineProperty(clone, key, descriptors[key]);
  285. delete descriptors[key];
  286. }
  287. }
  288. return clone;
  289. };
  290. return keys.map(split).concat(split(Object.keys(descriptors)));
  291. }
  292. function simpleMap(props, wrap) {
  293. const list = props.each || [],
  294. len = list.length,
  295. fn = props.children;
  296. if (len) {
  297. let mapped = "";
  298. for (let i = 0; i < len; i++) mapped += resolveSSRNode(wrap(fn, list[i], i));
  299. return {
  300. t: mapped
  301. };
  302. }
  303. return props.fallback || "";
  304. }
  305. function For(props) {
  306. return simpleMap(props, (fn, item, i) => fn(item, () => i));
  307. }
  308. function Index(props) {
  309. return simpleMap(props, (fn, item, i) => fn(() => item, i));
  310. }
  311. function Show(props) {
  312. let c;
  313. return props.when ? typeof (c = props.children) === "function" ? c(props.when) : c : props.fallback || "";
  314. }
  315. function Switch(props) {
  316. let conditions = props.children;
  317. Array.isArray(conditions) || (conditions = [conditions]);
  318. for (let i = 0; i < conditions.length; i++) {
  319. const w = conditions[i].when;
  320. if (w) {
  321. const c = conditions[i].children;
  322. return typeof c === "function" ? c(w) : c;
  323. }
  324. }
  325. return props.fallback || "";
  326. }
  327. function Match(props) {
  328. return props;
  329. }
  330. function ErrorBoundary(props) {
  331. return props.children;
  332. }
  333. const SuspenseContext = createContext();
  334. let resourceContext = null;
  335. function createResource(fn, fetcher, options = {}) {
  336. if (arguments.length === 2) {
  337. if (typeof fetcher === "object") {
  338. options = fetcher;
  339. fetcher = fn;
  340. fn = true;
  341. }
  342. } else if (arguments.length === 1) {
  343. fetcher = fn;
  344. fn = true;
  345. }
  346. const contexts = new Set();
  347. const id = sharedConfig.context.id + sharedConfig.context.count++;
  348. let resource = {};
  349. let value = options.initialValue;
  350. let p;
  351. if (sharedConfig.context.async) {
  352. resource = sharedConfig.context.resources[id] || (sharedConfig.context.resources[id] = {});
  353. if (resource.ref) {
  354. if (!resource.data && !resource.ref[0].loading) resource.ref[1].refetch();
  355. return resource.ref;
  356. }
  357. }
  358. const read = () => {
  359. if (resourceContext && p) resourceContext.push(p);
  360. const resolved = sharedConfig.context.async && sharedConfig.context.resources[id].data;
  361. if (sharedConfig.context.async && !resolved) {
  362. const ctx = useContext(SuspenseContext);
  363. if (ctx) {
  364. ctx.resources.set(id, read);
  365. contexts.add(ctx);
  366. }
  367. }
  368. return resolved ? sharedConfig.context.resources[id].data : value;
  369. };
  370. read.loading = false;
  371. function load() {
  372. const ctx = sharedConfig.context;
  373. if (!ctx.async && !ctx.streaming) return;
  374. if (ctx.resources && id in ctx.resources && ctx.resources[id].data) {
  375. value = ctx.resources[id].data;
  376. return;
  377. }
  378. resourceContext = [];
  379. const lookup = typeof fn === "function" ? fn() : fn;
  380. if (resourceContext.length) {
  381. p = Promise.all(resourceContext).then(() => fetcher(fn(), () => value));
  382. }
  383. resourceContext = null;
  384. if (!p) {
  385. if (lookup == null || lookup === false) return;
  386. p = fetcher(lookup, () => value);
  387. }
  388. read.loading = true;
  389. if ("then" in p) {
  390. if (ctx.writeResource) {
  391. ctx.writeResource(id, p);
  392. p.then(v => {
  393. value = v;
  394. read.loading = false;
  395. p = null;
  396. });
  397. return;
  398. }
  399. p.then(res => {
  400. read.loading = false;
  401. ctx.resources[id].data = res;
  402. p = null;
  403. notifySuspense(contexts);
  404. return res;
  405. });
  406. return;
  407. }
  408. ctx.resources[id].data = p;
  409. p = null;
  410. }
  411. load();
  412. return resource.ref = [read, {
  413. refetch: load,
  414. mutate: v => value = v
  415. }];
  416. }
  417. function lazy(fn) {
  418. let resolved;
  419. const p = fn();
  420. const contexts = new Set();
  421. p.then(mod => resolved = mod.default);
  422. const wrap = props => {
  423. const id = sharedConfig.context.id + sharedConfig.context.count++;
  424. if (resolved) return resolved(props);
  425. const ctx = useContext(SuspenseContext);
  426. const track = {
  427. loading: true
  428. };
  429. if (ctx) {
  430. ctx.resources.set(id, track);
  431. contexts.add(ctx);
  432. }
  433. p.then(() => {
  434. track.loading = false;
  435. notifySuspense(contexts);
  436. });
  437. return "";
  438. };
  439. wrap.preload = () => {};
  440. return wrap;
  441. }
  442. function suspenseComplete(c) {
  443. for (let r of c.resources.values()) {
  444. if (r.loading) return false;
  445. }
  446. return true;
  447. }
  448. function notifySuspense(contexts) {
  449. for (const c of contexts) {
  450. if (suspenseComplete(c)) c.completed();
  451. }
  452. contexts.clear();
  453. }
  454. function useTransition() {
  455. return [() => false, fn => {
  456. fn();
  457. }];
  458. }
  459. function SuspenseList(props) {
  460. return props.children;
  461. }
  462. const SUSPENSE_GLOBAL = Symbol("suspense-global");
  463. function Suspense(props) {
  464. const ctx = sharedConfig.context;
  465. if (ctx.streaming) createComponent(() => props.children, {});
  466. if (!ctx.async) return props.fallback;
  467. const id = ctx.id + ctx.count;
  468. const done = ctx.async ? lookup(Owner, SUSPENSE_GLOBAL)(id) : () => {};
  469. const o = Owner;
  470. const value = ctx.suspense[id] || (ctx.suspense[id] = {
  471. resources: new Map(),
  472. completed: () => {
  473. const res = runSuspense();
  474. if (suspenseComplete(value)) {
  475. done(resolveSSRNode(res));
  476. }
  477. }
  478. });
  479. function runSuspense() {
  480. setHydrateContext({ ...ctx,
  481. count: 0
  482. });
  483. return runWithOwner(o, () => {
  484. return createComponent(SuspenseContext.Provider, {
  485. value,
  486. get children() {
  487. return props.children;
  488. }
  489. });
  490. });
  491. }
  492. const res = runSuspense();
  493. if (suspenseComplete(value)) {
  494. done();
  495. return res;
  496. }
  497. return sharedConfig.context.async ? {
  498. t: `<#${id}#>`
  499. } : props.fallback;
  500. }
  501. const SUSPENSE_REPLACE = /<#([0-9\.]+)\#>/;
  502. function awaitSuspense(fn) {
  503. return new Promise(resolve => {
  504. const registry = new Set();
  505. const cache = Object.create(null);
  506. const res = createMemo(() => {
  507. Owner.context = {
  508. [SUSPENSE_GLOBAL]: getCallback
  509. };
  510. return fn();
  511. });
  512. if (!registry.size) resolve(res());
  513. function getCallback(key) {
  514. registry.add(key);
  515. return value => {
  516. if (value) cache[key] = value;
  517. registry.delete(key);
  518. if (!registry.size) Promise.resolve().then(() => {
  519. let source = resolveSSRNode(res());
  520. let final = "";
  521. let match;
  522. while (match = source.match(SUSPENSE_REPLACE)) {
  523. final += source.substring(0, match.index);
  524. source = cache[match[1]] + source.substring(match.index + match[0].length);
  525. }
  526. resolve(final + source);
  527. });
  528. };
  529. }
  530. });
  531. }
  532. export { $RAW, ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, awaitSuspense, batch, createComponent, createComputed, createContext, createDeferred, createEffect, createMemo, createRenderEffect, createResource, createRoot, createSelector, createSignal, createState, equalFn, getListener, getOwner, lazy, mapArray, mergeProps, on, onCleanup, onError, onMount, produce, reconcile, requestCallback, runWithOwner, sharedConfig, splitProps, untrack, unwrap, useContext, useTransition };