master
1(function() {
2 const CAT_namespace = 0;
3 const CAT_container = 1;
4 const CAT_global_variable = 2;
5 const CAT_function = 3;
6 const CAT_primitive = 4;
7 const CAT_error_set = 5;
8 const CAT_global_const = 6;
9 const CAT_alias = 7;
10 const CAT_type = 8;
11 const CAT_type_type = 9;
12 const CAT_type_function = 10;
13
14 const LOG_err = 0;
15 const LOG_warn = 1;
16 const LOG_info = 2;
17 const LOG_debug = 3;
18
19 const domDocTestsCode = document.getElementById("docTestsCode");
20 const domFnErrorsAnyError = document.getElementById("fnErrorsAnyError");
21 const domFnProto = document.getElementById("fnProto");
22 const domFnProtoCode = document.getElementById("fnProtoCode");
23 const domHdrName = document.getElementById("hdrName");
24 const domHelpModal = document.getElementById("helpDialog");
25 const domListErrSets = document.getElementById("listErrSets");
26 const domListFields = document.getElementById("listFields");
27 const domListParams = document.getElementById("listParams");
28 const domListFnErrors = document.getElementById("listFnErrors");
29 const domListFns = document.getElementById("listFns");
30 const domListGlobalVars = document.getElementById("listGlobalVars");
31 const domListInfo = document.getElementById("listInfo");
32 const domListNamespaces = document.getElementById("listNamespaces");
33 const domListNav = document.getElementById("listNav");
34 const domListSearchResults = document.getElementById("listSearchResults");
35 const domListTypes = document.getElementById("listTypes");
36 const domListValues = document.getElementById("listValues");
37 const domSearch = document.getElementById("search");
38 const domSectDocTests = document.getElementById("sectDocTests");
39 const domSectErrSets = document.getElementById("sectErrSets");
40 const domSectFields = document.getElementById("sectFields");
41 const domSectParams = document.getElementById("sectParams");
42 const domSectFnErrors = document.getElementById("sectFnErrors");
43 const domSectFns = document.getElementById("sectFns");
44 const domSectGlobalVars = document.getElementById("sectGlobalVars");
45 const domSectNamespaces = document.getElementById("sectNamespaces");
46 const domSectNav = document.getElementById("sectNav");
47 const domSectSearchNoResults = document.getElementById("sectSearchNoResults");
48 const domSectSearchResults = document.getElementById("sectSearchResults");
49 const domSectSource = document.getElementById("sectSource");
50 const domSectTypes = document.getElementById("sectTypes");
51 const domSectValues = document.getElementById("sectValues");
52 const domSourceText = document.getElementById("sourceText");
53 const domStatus = document.getElementById("status");
54 const domTableFnErrors = document.getElementById("tableFnErrors");
55 const domTldDocs = document.getElementById("tldDocs");
56 const domErrors = document.getElementById("errors");
57 const domErrorsText = document.getElementById("errorsText");
58
59 var searchTimer = null;
60
61 const curNav = {
62 // 0 = home
63 // 1 = decl (decl)
64 // 2 = source (path)
65 tag: 0,
66 // unsigned int: decl index
67 decl: null,
68 // string file name matching tarball path
69 path: null,
70
71 // when this is populated, pressing the "view source" command will
72 // navigate to this hash.
73 viewSourceHash: null,
74 };
75 var curNavSearch = "";
76 var curSearchIndex = -1;
77 var imFeelingLucky = false;
78
79 // names of modules in the same order as wasm
80 const moduleList = [];
81
82 let wasm_promise = fetch("main.wasm");
83 let sources_promise = fetch("sources.tar").then(function(response) {
84 if (!response.ok) throw new Error("unable to download sources");
85 return response.arrayBuffer();
86 });
87 var wasm_exports = null;
88
89 const text_decoder = new TextDecoder();
90 const text_encoder = new TextEncoder();
91
92 WebAssembly.instantiateStreaming(wasm_promise, {
93 js: {
94 log: function(level, ptr, len) {
95 const msg = decodeString(ptr, len);
96 switch (level) {
97 case LOG_err:
98 console.error(msg);
99 domErrorsText.textContent += msg + "\n";
100 domErrors.classList.remove("hidden");
101 break;
102 case LOG_warn:
103 console.warn(msg);
104 break;
105 case LOG_info:
106 console.info(msg);
107 break;
108 case LOG_debug:
109 console.debug(msg);
110 break;
111 }
112 },
113 },
114 }).then(function(obj) {
115 wasm_exports = obj.instance.exports;
116 window.wasm = obj; // for debugging
117
118 sources_promise.then(function(buffer) {
119 const js_array = new Uint8Array(buffer);
120 const ptr = wasm_exports.alloc(js_array.length);
121 const wasm_array = new Uint8Array(wasm_exports.memory.buffer, ptr, js_array.length);
122 wasm_array.set(js_array);
123 wasm_exports.unpack(ptr, js_array.length);
124
125 updateModuleList();
126
127 window.addEventListener('popstate', onPopState, false);
128 domSearch.addEventListener('keydown', onSearchKeyDown, false);
129 domSearch.addEventListener('input', onSearchChange, false);
130 window.addEventListener('keydown', onWindowKeyDown, false);
131 onHashChange(null);
132 if (domSearch.value) {
133 // user started typing a search query while the page was loading
134 curSearchIndex = -1;
135 startAsyncSearch();
136 }
137 });
138 });
139
140 function renderTitle() {
141 const suffix = " - Zig Documentation";
142 if (curNavSearch.length > 0) {
143 document.title = curNavSearch + " - Search" + suffix;
144 } else if (curNav.decl != null) {
145 document.title = fullyQualifiedName(curNav.decl) + suffix;
146 } else if (curNav.path != null) {
147 document.title = curNav.path + suffix;
148 } else {
149 document.title = moduleList[0] + suffix; // Home
150 }
151 }
152
153 function render() {
154 domFnErrorsAnyError.classList.add("hidden");
155 domFnProto.classList.add("hidden");
156 domHdrName.classList.add("hidden");
157 domHelpModal.classList.add("hidden");
158 domSectErrSets.classList.add("hidden");
159 domSectDocTests.classList.add("hidden");
160 domSectFields.classList.add("hidden");
161 domSectParams.classList.add("hidden");
162 domSectFnErrors.classList.add("hidden");
163 domSectFns.classList.add("hidden");
164 domSectGlobalVars.classList.add("hidden");
165 domSectNamespaces.classList.add("hidden");
166 domSectNav.classList.add("hidden");
167 domSectSearchNoResults.classList.add("hidden");
168 domSectSearchResults.classList.add("hidden");
169 domSectSource.classList.add("hidden");
170 domSectTypes.classList.add("hidden");
171 domSectValues.classList.add("hidden");
172 domStatus.classList.add("hidden");
173 domTableFnErrors.classList.add("hidden");
174 domTldDocs.classList.add("hidden");
175
176 renderTitle();
177
178 if (curNavSearch !== "") return renderSearch();
179
180 switch (curNav.tag) {
181 case 0: return renderHome();
182 case 1:
183 if (curNav.decl == null) {
184 return renderNotFound();
185 } else {
186 return renderDecl(curNav.decl);
187 }
188 case 2: return renderSource(curNav.path);
189 default: throw new Error("invalid navigation state");
190 }
191 }
192
193 function renderHome() {
194 if (moduleList.length == 0) {
195 domStatus.textContent = "sources.tar contains no modules";
196 domStatus.classList.remove("hidden");
197 return;
198 }
199 return renderModule(0);
200 }
201
202 function renderModule(pkg_index) {
203 const root_decl = wasm_exports.find_module_root(pkg_index);
204 return renderDecl(root_decl);
205 }
206
207 function renderDecl(decl_index) {
208 const category = wasm_exports.categorize_decl(decl_index, 0);
209 switch (category) {
210 case CAT_namespace:
211 case CAT_container:
212 return renderNamespacePage(decl_index);
213 case CAT_global_variable:
214 case CAT_primitive:
215 case CAT_global_const:
216 case CAT_type:
217 case CAT_type_type:
218 return renderGlobal(decl_index);
219 case CAT_function:
220 return renderFunction(decl_index);
221 case CAT_type_function:
222 return renderTypeFunction(decl_index);
223 case CAT_error_set:
224 return renderErrorSetPage(decl_index);
225 case CAT_alias:
226 return renderDecl(wasm_exports.get_aliasee());
227 default:
228 throw new Error("unrecognized category " + category);
229 }
230 }
231
232 function renderSource(path) {
233 const decl_index = findFileRoot(path);
234 if (decl_index == null) return renderNotFound();
235
236 renderNavFancy(decl_index, [{
237 name: "[src]",
238 href: location.hash,
239 }]);
240
241 domSourceText.innerHTML = declSourceHtml(decl_index);
242
243 domSectSource.classList.remove("hidden");
244 }
245
246 function renderDeclHeading(decl_index) {
247 curNav.viewSourceHash = "#src/" + unwrapString(wasm_exports.decl_file_path(decl_index));
248
249 const hdrNameSpan = domHdrName.children[0];
250 const srcLink = domHdrName.children[1];
251 hdrNameSpan.innerText = unwrapString(wasm_exports.decl_category_name(decl_index));
252 srcLink.setAttribute('href', curNav.viewSourceHash);
253 domHdrName.classList.remove("hidden");
254
255 renderTopLevelDocs(decl_index);
256 }
257
258 function renderTopLevelDocs(decl_index) {
259 const tld_docs_html = unwrapString(wasm_exports.decl_docs_html(decl_index, false));
260 if (tld_docs_html.length > 0) {
261 domTldDocs.innerHTML = tld_docs_html;
262 domTldDocs.classList.remove("hidden");
263 }
264 }
265
266 function renderNav(cur_nav_decl, list) {
267 return renderNavFancy(cur_nav_decl, []);
268 }
269
270 function renderNavFancy(cur_nav_decl, list) {
271 {
272 // First, walk backwards the decl parents within a file.
273 let decl_it = cur_nav_decl;
274 let prev_decl_it = null;
275 while (decl_it != null) {
276 list.push({
277 name: declIndexName(decl_it),
278 href: navLinkDeclIndex(decl_it),
279 });
280 prev_decl_it = decl_it;
281 decl_it = declParent(decl_it);
282 }
283
284 // Next, walk backwards the file path segments.
285 if (prev_decl_it != null) {
286 const file_path = fullyQualifiedName(prev_decl_it);
287 const parts = file_path.split(".");
288 parts.pop(); // skip last
289 for (;;) {
290 const href = navLinkFqn(parts.join("."));
291 const part = parts.pop();
292 if (!part) break;
293 list.push({
294 name: part,
295 href: href,
296 });
297 }
298 }
299
300 list.reverse();
301 }
302 resizeDomList(domListNav, list.length, '<li><a href="#"></a></li>');
303
304 for (let i = 0; i < list.length; i += 1) {
305 const liDom = domListNav.children[i];
306 const aDom = liDom.children[0];
307 aDom.textContent = list[i].name;
308 aDom.setAttribute('href', list[i].href);
309 if (i + 1 == list.length) {
310 aDom.classList.add("active");
311 } else {
312 aDom.classList.remove("active");
313 }
314 }
315
316 domSectNav.classList.remove("hidden");
317 }
318
319 function renderNotFound() {
320 domStatus.textContent = "Declaration not found.";
321 domStatus.classList.remove("hidden");
322 }
323
324 function navLinkFqn(full_name) {
325 return '#' + full_name;
326 }
327
328 function navLinkDeclIndex(decl_index) {
329 return navLinkFqn(fullyQualifiedName(decl_index));
330 }
331
332 function resizeDomList(listDom, desiredLen, templateHtml) {
333 // add the missing dom entries
334 var i, ev;
335 for (i = listDom.childElementCount; i < desiredLen; i += 1) {
336 listDom.insertAdjacentHTML('beforeend', templateHtml);
337 }
338 // remove extra dom entries
339 while (desiredLen < listDom.childElementCount) {
340 listDom.removeChild(listDom.lastChild);
341 }
342 }
343
344 function renderErrorSetPage(decl_index) {
345 renderNav(decl_index);
346 renderDeclHeading(decl_index);
347
348 const errorSetList = declErrorSet(decl_index).slice();
349 renderErrorSet(decl_index, errorSetList);
350 }
351
352 function renderErrorSet(base_decl, errorSetList) {
353 if (errorSetList == null) {
354 domFnErrorsAnyError.classList.remove("hidden");
355 } else {
356 resizeDomList(domListFnErrors, errorSetList.length, '<div></div>');
357 for (let i = 0; i < errorSetList.length; i += 1) {
358 const divDom = domListFnErrors.children[i];
359 const html = unwrapString(wasm_exports.error_html(base_decl, errorSetList[i]));
360 divDom.innerHTML = html;
361 }
362 domTableFnErrors.classList.remove("hidden");
363 }
364 domSectFnErrors.classList.remove("hidden");
365 }
366
367 function renderParams(decl_index) {
368 // Prevent params from being emptied next time wasm calls memory.grow.
369 const params = declParams(decl_index).slice();
370 if (params.length !== 0) {
371 resizeDomList(domListParams, params.length, '<div></div>');
372 for (let i = 0; i < params.length; i += 1) {
373 const divDom = domListParams.children[i];
374 divDom.innerHTML = unwrapString(wasm_exports.decl_param_html(decl_index, params[i]));
375 }
376 domSectParams.classList.remove("hidden");
377 }
378 }
379
380 function renderTypeFunction(decl_index) {
381 renderNav(decl_index);
382 renderDeclHeading(decl_index);
383 renderTopLevelDocs(decl_index);
384 renderParams(decl_index);
385 renderDocTests(decl_index);
386
387 const members = unwrapSlice32(wasm_exports.type_fn_members(decl_index, false)).slice();
388 const fields = unwrapSlice32(wasm_exports.type_fn_fields(decl_index)).slice();
389 if (members.length !== 0 || fields.length !== 0) {
390 renderNamespace(decl_index, members, fields);
391 } else {
392 domSourceText.innerHTML = declSourceHtml(decl_index);
393 domSectSource.classList.remove("hidden");
394 }
395 }
396
397 function renderDocTests(decl_index) {
398 const doctest_html = declDoctestHtml(decl_index);
399 if (doctest_html.length > 0) {
400 domDocTestsCode.innerHTML = doctest_html;
401 domSectDocTests.classList.remove("hidden");
402 }
403 }
404
405 function renderFunction(decl_index) {
406 renderNav(decl_index);
407 renderDeclHeading(decl_index);
408 renderTopLevelDocs(decl_index);
409 renderParams(decl_index);
410 renderDocTests(decl_index);
411
412 domFnProtoCode.innerHTML = fnProtoHtml(decl_index, false);
413 domFnProto.classList.remove("hidden");
414
415
416 const errorSetNode = fnErrorSet(decl_index);
417 if (errorSetNode != null) {
418 const base_decl = wasm_exports.fn_error_set_decl(decl_index, errorSetNode);
419 renderErrorSet(base_decl, errorSetNodeList(decl_index, errorSetNode));
420 }
421
422 domSourceText.innerHTML = declSourceHtml(decl_index);
423 domSectSource.classList.remove("hidden");
424 }
425
426 function renderGlobal(decl_index) {
427 renderNav(decl_index);
428 renderDeclHeading(decl_index);
429
430 const docs_html = declDocsHtmlShort(decl_index);
431 if (docs_html.length > 0) {
432 domTldDocs.innerHTML = docs_html;
433 domTldDocs.classList.remove("hidden");
434 }
435
436 domSourceText.innerHTML = declSourceHtml(decl_index);
437 domSectSource.classList.remove("hidden");
438 }
439
440 function renderNamespace(base_decl, members, fields) {
441 const typesList = [];
442 const namespacesList = [];
443 const errSetsList = [];
444 const fnsList = [];
445 const varsList = [];
446 const valsList = [];
447
448 member_loop: for (let i = 0; i < members.length; i += 1) {
449 let member = members[i];
450 const original = member;
451 while (true) {
452 const member_category = wasm_exports.categorize_decl(member, 0);
453 switch (member_category) {
454 case CAT_namespace:
455 namespacesList.push({original: original, member: member});
456 continue member_loop;
457 case CAT_container:
458 typesList.push({original: original, member: member});
459 continue member_loop;
460 case CAT_global_variable:
461 varsList.push(member);
462 continue member_loop;
463 case CAT_function:
464 fnsList.push(member);
465 continue member_loop;
466 case CAT_type:
467 case CAT_type_type:
468 case CAT_type_function:
469 typesList.push({original: original, member: member});
470 continue member_loop;
471 case CAT_error_set:
472 errSetsList.push({original: original, member: member});
473 continue member_loop;
474 case CAT_global_const:
475 case CAT_primitive:
476 valsList.push({original: original, member: member});
477 continue member_loop;
478 case CAT_alias:
479 member = wasm_exports.get_aliasee();
480 continue;
481 default:
482 throw new Error("uknown category: " + member_category);
483 }
484 }
485 }
486
487 typesList.sort(byDeclIndexName2);
488 namespacesList.sort(byDeclIndexName2);
489 errSetsList.sort(byDeclIndexName2);
490 fnsList.sort(byDeclIndexName);
491 varsList.sort(byDeclIndexName);
492 valsList.sort(byDeclIndexName2);
493
494 if (typesList.length !== 0) {
495 resizeDomList(domListTypes, typesList.length, '<li><a href="#"></a></li>');
496 for (let i = 0; i < typesList.length; i += 1) {
497 const liDom = domListTypes.children[i];
498 const aDom = liDom.children[0];
499 const original_decl = typesList[i].original;
500 const decl = typesList[i].member;
501 aDom.textContent = declIndexName(original_decl);
502 aDom.setAttribute('href', navLinkDeclIndex(decl));
503 }
504 domSectTypes.classList.remove("hidden");
505 }
506 if (namespacesList.length !== 0) {
507 resizeDomList(domListNamespaces, namespacesList.length, '<li><a href="#"></a></li>');
508 for (let i = 0; i < namespacesList.length; i += 1) {
509 const liDom = domListNamespaces.children[i];
510 const aDom = liDom.children[0];
511 const original_decl = namespacesList[i].original;
512 const decl = namespacesList[i].member;
513 aDom.textContent = declIndexName(original_decl);
514 aDom.setAttribute('href', navLinkDeclIndex(decl));
515 }
516 domSectNamespaces.classList.remove("hidden");
517 }
518
519 if (errSetsList.length !== 0) {
520 resizeDomList(domListErrSets, errSetsList.length, '<li><a href="#"></a></li>');
521 for (let i = 0; i < errSetsList.length; i += 1) {
522 const liDom = domListErrSets.children[i];
523 const aDom = liDom.children[0];
524 const original_decl = errSetsList[i].original;
525 const decl = errSetsList[i].member;
526 aDom.textContent = declIndexName(original_decl);
527 aDom.setAttribute('href', navLinkDeclIndex(decl));
528 }
529 domSectErrSets.classList.remove("hidden");
530 }
531
532 if (fnsList.length !== 0) {
533 resizeDomList(domListFns, fnsList.length,
534 '<div><dt><code></code></dt><dd></dd></div>');
535 for (let i = 0; i < fnsList.length; i += 1) {
536 const decl = fnsList[i];
537 const divDom = domListFns.children[i];
538
539 const dtDom = divDom.children[0];
540 const ddDocs = divDom.children[1];
541 const protoCodeDom = dtDom.children[0];
542
543 protoCodeDom.innerHTML = fnProtoHtml(decl, true);
544 ddDocs.innerHTML = declDocsHtmlShort(decl);
545 }
546 domSectFns.classList.remove("hidden");
547 }
548
549 if (fields.length !== 0) {
550 resizeDomList(domListFields, fields.length, '<div></div>');
551 for (let i = 0; i < fields.length; i += 1) {
552 const divDom = domListFields.children[i];
553 divDom.innerHTML = unwrapString(wasm_exports.decl_field_html(base_decl, fields[i]));
554 }
555 domSectFields.classList.remove("hidden");
556 }
557
558 if (varsList.length !== 0) {
559 resizeDomList(domListGlobalVars, varsList.length,
560 '<tr><td><a href="#"></a></td><td></td><td></td></tr>');
561 for (let i = 0; i < varsList.length; i += 1) {
562 const decl = varsList[i];
563 const trDom = domListGlobalVars.children[i];
564
565 const tdName = trDom.children[0];
566 const tdNameA = tdName.children[0];
567 const tdType = trDom.children[1];
568 const tdDesc = trDom.children[2];
569
570 tdNameA.setAttribute('href', navLinkDeclIndex(decl));
571 tdNameA.textContent = declIndexName(decl);
572
573 tdType.innerHTML = declTypeHtml(decl);
574 tdDesc.innerHTML = declDocsHtmlShort(decl);
575 }
576 domSectGlobalVars.classList.remove("hidden");
577 }
578
579 if (valsList.length !== 0) {
580 resizeDomList(domListValues, valsList.length,
581 '<tr><td><a href="#"></a></td><td></td><td></td></tr>');
582 for (let i = 0; i < valsList.length; i += 1) {
583 const trDom = domListValues.children[i];
584 const tdName = trDom.children[0];
585 const tdNameA = tdName.children[0];
586 const tdType = trDom.children[1];
587 const tdDesc = trDom.children[2];
588
589 const original_decl = valsList[i].original;
590 const decl = valsList[i].member;
591 tdNameA.setAttribute('href', navLinkDeclIndex(decl));
592 tdNameA.textContent = declIndexName(original_decl);
593
594 tdType.innerHTML = declTypeHtml(decl);
595 tdDesc.innerHTML = declDocsHtmlShort(decl);
596 }
597 domSectValues.classList.remove("hidden");
598 }
599 }
600
601 function renderNamespacePage(decl_index) {
602 renderNav(decl_index);
603 renderDeclHeading(decl_index);
604 const members = namespaceMembers(decl_index, false).slice();
605 const fields = declFields(decl_index).slice();
606 renderNamespace(decl_index, members, fields);
607 }
608
609 function operatorCompare(a, b) {
610 if (a === b) {
611 return 0;
612 } else if (a < b) {
613 return -1;
614 } else {
615 return 1;
616 }
617 }
618
619 function updateCurNav(location_hash) {
620 curNav.tag = 0;
621 curNav.decl = null;
622 curNav.path = null;
623 curNav.viewSourceHash = null;
624 curNavSearch = "";
625
626 if (location_hash.length > 1 && location_hash[0] === '#') {
627 const query = location_hash.substring(1);
628 const qpos = query.indexOf("?");
629 let nonSearchPart;
630 if (qpos === -1) {
631 nonSearchPart = query;
632 } else {
633 nonSearchPart = query.substring(0, qpos);
634 curNavSearch = decodeURIComponent(query.substring(qpos + 1));
635 }
636
637 if (nonSearchPart.length > 0) {
638 const source_mode = nonSearchPart.startsWith("src/");
639 if (source_mode) {
640 curNav.tag = 2;
641 curNav.path = nonSearchPart.substring(4);
642 } else {
643 curNav.tag = 1;
644 curNav.decl = findDecl(nonSearchPart);
645 }
646 }
647 }
648 }
649
650 function onHashChange(state) {
651 // Use a non-null state value to prevent the window scrolling if the user goes back to this history entry.
652 history.replaceState({}, "");
653 navigate(location.hash);
654 if (state == null) window.scrollTo({top: 0});
655 }
656
657 function onPopState(ev) {
658 onHashChange(ev.state);
659 syncDomSearch();
660 }
661
662 function navigate(location_hash) {
663 updateCurNav(location_hash);
664 render();
665 if (imFeelingLucky) {
666 imFeelingLucky = false;
667 activateSelectedResult();
668 }
669 }
670
671 function syncDomSearch() {
672 if (domSearch.value !== curNavSearch) {
673 domSearch.value = curNavSearch;
674 }
675 }
676
677 function activateSelectedResult() {
678 if (domSectSearchResults.classList.contains("hidden")) {
679 return;
680 }
681
682 var liDom = domListSearchResults.children[curSearchIndex];
683 if (liDom == null && domListSearchResults.children.length !== 0) {
684 liDom = domListSearchResults.children[0];
685 }
686 if (liDom != null) {
687 var aDom = liDom.children[0];
688 location.href = aDom.getAttribute("href");
689 curSearchIndex = -1;
690 }
691 domSearch.blur();
692 }
693
694 function onSearchKeyDown(ev) {
695 switch (ev.code) {
696 case "Enter":
697 if (ev.shiftKey || ev.ctrlKey || ev.altKey) return;
698
699 clearAsyncSearch();
700 imFeelingLucky = true;
701 location.hash = computeSearchHash();
702
703 ev.preventDefault();
704 ev.stopPropagation();
705 return;
706 case "Escape":
707 if (ev.shiftKey || ev.ctrlKey || ev.altKey) return;
708
709 domSearch.value = "";
710 domSearch.blur();
711 curSearchIndex = -1;
712 ev.preventDefault();
713 ev.stopPropagation();
714 startSearch();
715 return;
716 case "ArrowUp":
717 if (ev.shiftKey || ev.ctrlKey || ev.altKey) return;
718
719 moveSearchCursor(-1);
720 ev.preventDefault();
721 ev.stopPropagation();
722 return;
723 case "ArrowDown":
724 if (ev.shiftKey || ev.ctrlKey || ev.altKey) return;
725
726 moveSearchCursor(1);
727 ev.preventDefault();
728 ev.stopPropagation();
729 return;
730 default:
731 ev.stopPropagation(); // prevent keyboard shortcuts
732 return;
733 }
734 }
735
736 function onSearchChange(ev) {
737 curSearchIndex = -1;
738 startAsyncSearch();
739 }
740
741 function moveSearchCursor(dir) {
742 if (curSearchIndex < 0 || curSearchIndex >= domListSearchResults.children.length) {
743 if (dir > 0) {
744 curSearchIndex = -1 + dir;
745 } else if (dir < 0) {
746 curSearchIndex = domListSearchResults.children.length + dir;
747 }
748 } else {
749 curSearchIndex += dir;
750 }
751 if (curSearchIndex < 0) {
752 curSearchIndex = 0;
753 }
754 if (curSearchIndex >= domListSearchResults.children.length) {
755 curSearchIndex = domListSearchResults.children.length - 1;
756 }
757 renderSearchCursor();
758 }
759
760 function onWindowKeyDown(ev) {
761 switch (ev.code) {
762 case "Escape":
763 if (ev.shiftKey || ev.ctrlKey || ev.altKey) return;
764 if (!domHelpModal.classList.contains("hidden")) {
765 domHelpModal.classList.add("hidden");
766 ev.preventDefault();
767 ev.stopPropagation();
768 }
769 break;
770 case "KeyS":
771 if (ev.shiftKey || ev.ctrlKey || ev.altKey) return;
772 domSearch.focus();
773 domSearch.select();
774 ev.preventDefault();
775 ev.stopPropagation();
776 startAsyncSearch();
777 break;
778 case "KeyU":
779 if (ev.shiftKey || ev.ctrlKey || ev.altKey) return;
780 ev.preventDefault();
781 ev.stopPropagation();
782 navigateToSource();
783 break;
784 case "Slash":
785 if (!ev.shiftKey || ev.ctrlKey || ev.altKey) return;
786 ev.preventDefault();
787 ev.stopPropagation();
788 showHelpModal();
789 break;
790 }
791 }
792
793 function showHelpModal() {
794 domHelpModal.classList.remove("hidden");
795 domHelpModal.style.left = (window.innerWidth / 2 - domHelpModal.clientWidth / 2) + "px";
796 domHelpModal.style.top = (window.innerHeight / 2 - domHelpModal.clientHeight / 2) + "px";
797 domHelpModal.focus();
798 }
799
800 function navigateToSource() {
801 if (curNav.viewSourceHash != null) {
802 location.hash = curNav.viewSourceHash;
803 }
804 }
805
806 function clearAsyncSearch() {
807 if (searchTimer != null) {
808 clearTimeout(searchTimer);
809 searchTimer = null;
810 }
811 }
812
813 function startAsyncSearch() {
814 clearAsyncSearch();
815 searchTimer = setTimeout(startSearch, 10);
816 }
817 function computeSearchHash() {
818 // How location.hash works:
819 // 1. http://example.com/ => ""
820 // 2. http://example.com/# => ""
821 // 3. http://example.com/#foo => "#foo"
822 // wat
823 const oldWatHash = location.hash;
824 const oldHash = oldWatHash.startsWith("#") ? oldWatHash : "#" + oldWatHash;
825 const parts = oldHash.split("?");
826 const newPart2 = (domSearch.value === "") ? "" : ("?" + domSearch.value);
827 return parts[0] + newPart2;
828 }
829 function startSearch() {
830 clearAsyncSearch();
831 navigate(computeSearchHash());
832 }
833 function renderSearch() {
834 renderNav(curNav.decl);
835
836 const ignoreCase = (curNavSearch.toLowerCase() === curNavSearch);
837 const results = executeQuery(curNavSearch, ignoreCase);
838
839 if (results.length !== 0) {
840 resizeDomList(domListSearchResults, results.length, '<li><a href="#"></a></li>');
841
842 for (let i = 0; i < results.length; i += 1) {
843 const liDom = domListSearchResults.children[i];
844 const aDom = liDom.children[0];
845 const match = results[i];
846 const full_name = fullyQualifiedName(match);
847 aDom.textContent = full_name;
848 aDom.setAttribute('href', navLinkFqn(full_name));
849 }
850 renderSearchCursor();
851
852 domSectSearchResults.classList.remove("hidden");
853 } else {
854 domSectSearchNoResults.classList.remove("hidden");
855 }
856 }
857
858 function renderSearchCursor() {
859 for (let i = 0; i < domListSearchResults.children.length; i += 1) {
860 var liDom = domListSearchResults.children[i];
861 if (curSearchIndex === i) {
862 liDom.classList.add("selected");
863 } else {
864 liDom.classList.remove("selected");
865 }
866 }
867 }
868
869 function updateModuleList() {
870 moduleList.length = 0;
871 for (let i = 0;; i += 1) {
872 const name = unwrapString(wasm_exports.module_name(i));
873 if (name.length == 0) break;
874 moduleList.push(name);
875 }
876 }
877
878 function byDeclIndexName(a, b) {
879 const a_name = declIndexName(a);
880 const b_name = declIndexName(b);
881 return operatorCompare(a_name, b_name);
882 }
883
884 function byDeclIndexName2(a, b) {
885 const a_name = declIndexName(a.original);
886 const b_name = declIndexName(b.original);
887 return operatorCompare(a_name, b_name);
888 }
889
890 function decodeString(ptr, len) {
891 if (len === 0) return "";
892 return text_decoder.decode(new Uint8Array(wasm_exports.memory.buffer, ptr, len));
893 }
894
895 function unwrapString(bigint) {
896 const ptr = Number(bigint & 0xffffffffn);
897 const len = Number(bigint >> 32n);
898 return decodeString(ptr, len);
899 }
900
901 function declTypeHtml(decl_index) {
902 return unwrapString(wasm_exports.decl_type_html(decl_index));
903 }
904
905 function declDocsHtmlShort(decl_index) {
906 return unwrapString(wasm_exports.decl_docs_html(decl_index, true));
907 }
908
909 function fullyQualifiedName(decl_index) {
910 return unwrapString(wasm_exports.decl_fqn(decl_index));
911 }
912
913 function declIndexName(decl_index) {
914 return unwrapString(wasm_exports.decl_name(decl_index));
915 }
916
917 function declSourceHtml(decl_index) {
918 return unwrapString(wasm_exports.decl_source_html(decl_index));
919 }
920
921 function declDoctestHtml(decl_index) {
922 return unwrapString(wasm_exports.decl_doctest_html(decl_index));
923 }
924
925 function fnProtoHtml(decl_index, linkify_fn_name) {
926 return unwrapString(wasm_exports.decl_fn_proto_html(decl_index, linkify_fn_name));
927 }
928
929 function setQueryString(s) {
930 const jsArray = text_encoder.encode(s);
931 const len = jsArray.length;
932 const ptr = wasm_exports.query_begin(len);
933 const wasmArray = new Uint8Array(wasm_exports.memory.buffer, ptr, len);
934 wasmArray.set(jsArray);
935 }
936
937 function executeQuery(query_string, ignore_case) {
938 setQueryString(query_string);
939 const ptr = wasm_exports.query_exec(ignore_case);
940 const head = new Uint32Array(wasm_exports.memory.buffer, ptr, 1);
941 const len = head[0];
942 return new Uint32Array(wasm_exports.memory.buffer, ptr + 4, len);
943 }
944
945 function namespaceMembers(decl_index, include_private) {
946 return unwrapSlice32(wasm_exports.namespace_members(decl_index, include_private));
947 }
948
949 function declFields(decl_index) {
950 return unwrapSlice32(wasm_exports.decl_fields(decl_index));
951 }
952
953 function declParams(decl_index) {
954 return unwrapSlice32(wasm_exports.decl_params(decl_index));
955 }
956
957 function declErrorSet(decl_index) {
958 return unwrapSlice64(wasm_exports.decl_error_set(decl_index));
959 }
960
961 function errorSetNodeList(base_decl, err_set_node) {
962 return unwrapSlice64(wasm_exports.error_set_node_list(base_decl, err_set_node));
963 }
964
965 function unwrapSlice32(bigint) {
966 const ptr = Number(bigint & 0xffffffffn);
967 const len = Number(bigint >> 32n);
968 if (len === 0) return [];
969 return new Uint32Array(wasm_exports.memory.buffer, ptr, len);
970 }
971
972 function unwrapSlice64(bigint) {
973 const ptr = Number(bigint & 0xffffffffn);
974 const len = Number(bigint >> 32n);
975 if (len === 0) return [];
976 return new BigUint64Array(wasm_exports.memory.buffer, ptr, len);
977 }
978
979 function findDecl(fqn) {
980 setInputString(fqn);
981 const result = wasm_exports.find_decl();
982 if (result === -1) return null;
983 return result;
984 }
985
986 function findFileRoot(path) {
987 setInputString(path);
988 const result = wasm_exports.find_file_root();
989 if (result === -1) return null;
990 return result;
991 }
992
993 function declParent(decl_index) {
994 const result = wasm_exports.decl_parent(decl_index);
995 if (result === -1) return null;
996 return result;
997 }
998
999 function fnErrorSet(decl_index) {
1000 const result = wasm_exports.fn_error_set(decl_index);
1001 if (result === 0) return null;
1002 return result;
1003 }
1004
1005 function setInputString(s) {
1006 const jsArray = text_encoder.encode(s);
1007 const len = jsArray.length;
1008 const ptr = wasm_exports.set_input_string(len);
1009 const wasmArray = new Uint8Array(wasm_exports.memory.buffer, ptr, len);
1010 wasmArray.set(jsArray);
1011 }
1012})();
1013