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