about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-12-14 20:33:10 +0100
committerGitHub <noreply@github.com>2023-12-14 20:33:10 +0100
commit9ec620546f185d3776f312a0b0949bb2612500e6 (patch)
treef1d5a21b86ca0c8c8c2b76a7992cbb93b052b7ec
parent2ecba0fa00b75e7291978c50bece407f17296f45 (diff)
parentfc7221689e6dcb32dbf72befa465d851d92263d8 (diff)
downloadrust-9ec620546f185d3776f312a0b0949bb2612500e6.tar.gz
rust-9ec620546f185d3776f312a0b0949bb2612500e6.zip
Rollup merge of #118910 - GuillaumeGomez:js-object-to-map, r=notriddle
[rustdoc] Use Map instead of Object for source files and search index

It's cleaner and is also easier to manipulate `Map` rather than `Object` types.

r? `@notriddle`
-rw-r--r--src/librustdoc/html/render/search_index.rs2
-rw-r--r--src/librustdoc/html/render/write_shared.rs19
-rw-r--r--src/librustdoc/html/static/js/search.js141
-rw-r--r--src/librustdoc/html/static/js/src-script.js8
4 files changed, 77 insertions, 93 deletions
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index b3ae720fcf6..a1029320d2d 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -488,7 +488,7 @@ pub(crate) fn build_index<'tcx>(
 
     // Collect the index into a string
     format!(
-        r#""{}":{}"#,
+        r#"["{}",{}]"#,
         krate.name(tcx),
         serde_json::to_string(&CrateData {
             doc: crate_doc,
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index b04776e91dc..4b5d1c0d87c 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -167,23 +167,24 @@ pub(super) fn write_shared(
         let mut krates = Vec::new();
 
         if path.exists() {
-            let prefix = format!("\"{krate}\"");
+            let prefix = format!("[\"{krate}\"");
             for line in BufReader::new(File::open(path)?).lines() {
                 let line = line?;
-                if !line.starts_with('"') {
+                if !line.starts_with("[\"") {
                     continue;
                 }
                 if line.starts_with(&prefix) {
                     continue;
                 }
-                if line.ends_with(",\\") {
+                if line.ends_with("],\\") {
                     ret.push(line[..line.len() - 2].to_string());
                 } else {
                     // Ends with "\\" (it's the case for the last added crate line)
                     ret.push(line[..line.len() - 1].to_string());
                 }
                 krates.push(
-                    line.split('"')
+                    line[1..] // We skip the `[` parent at the beginning of the line.
+                        .split('"')
                         .find(|s| !s.is_empty())
                         .map(|s| s.to_owned())
                         .unwrap_or_else(String::new),
@@ -285,7 +286,7 @@ pub(super) fn write_shared(
             let (mut all_sources, _krates) =
                 try_err!(collect_json(&dst, krate.name(cx.tcx()).as_str()), &dst);
             all_sources.push(format!(
-                r#""{}":{}"#,
+                r#"["{}",{}]"#,
                 &krate.name(cx.tcx()),
                 hierarchy
                     .to_json_string()
@@ -296,9 +297,9 @@ pub(super) fn write_shared(
                     .replace("\\\"", "\\\\\"")
             ));
             all_sources.sort();
-            let mut v = String::from("var srcIndex = JSON.parse('{\\\n");
+            let mut v = String::from("const srcIndex = new Map(JSON.parse('[\\\n");
             v.push_str(&all_sources.join(",\\\n"));
-            v.push_str("\\\n}');\ncreateSrcSidebar();\n");
+            v.push_str("\\\n]'));\ncreateSrcSidebar();\n");
             Ok(v.into_bytes())
         };
         write_invocation_specific("src-files.js", &make_sources)?;
@@ -316,11 +317,11 @@ pub(super) fn write_shared(
     // with rustdoc running in parallel.
     all_indexes.sort();
     write_invocation_specific("search-index.js", &|| {
-        let mut v = String::from("var searchIndex = JSON.parse('{\\\n");
+        let mut v = String::from("const searchIndex = new Map(JSON.parse('[\\\n");
         v.push_str(&all_indexes.join(",\\\n"));
         v.push_str(
             r#"\
-}');
+]'));
 if (typeof window !== 'undefined' && window.initSearch) {window.initSearch(searchIndex)};
 if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
 "#,
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 6fce7650b4c..ccb54e14a5c 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -80,10 +80,6 @@ const longItemTypes = [
 const TY_GENERIC = itemTypes.indexOf("generic");
 const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../";
 
-function hasOwnPropertyRustdoc(obj, property) {
-    return Object.prototype.hasOwnProperty.call(obj, property);
-}
-
 // In the search display, allows to switch between tabs.
 function printTab(nb) {
     let iter = 0;
@@ -1074,7 +1070,7 @@ function initSearch(rawSearchIndex) {
 
         if (elem &&
             elem.value !== "all crates" &&
-            hasOwnPropertyRustdoc(rawSearchIndex, elem.value)
+            rawSearchIndex.has(elem.value)
         ) {
             return elem.value;
         }
@@ -2524,11 +2520,10 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         }
 
         let crates = "";
-        const crates_list = Object.keys(rawSearchIndex);
-        if (crates_list.length > 1) {
+        if (rawSearchIndex.size > 1) {
             crates = " in&nbsp;<div id=\"crate-search-div\"><select id=\"crate-search\">" +
                 "<option value=\"all crates\">all crates</option>";
-            for (const c of crates_list) {
+            for (const c of rawSearchIndex.keys()) {
                 crates += `<option value="${c}" ${c === filterCrates && "selected"}>${c}</option>`;
             }
             crates += "</select></div>";
@@ -2945,81 +2940,70 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         // Function type fingerprints are 128-bit bloom filters that are used to
         // estimate the distance between function and query.
         // This loop counts the number of items to allocate a fingerprint for.
-        for (const crate in rawSearchIndex) {
-            if (!hasOwnPropertyRustdoc(rawSearchIndex, crate)) {
-                continue;
-            }
+        for (const crate of rawSearchIndex.values()) {
             // Each item gets an entry in the fingerprint array, and the crate
             // does, too
-            id += rawSearchIndex[crate].t.length + 1;
+            id += crate.t.length + 1;
         }
         functionTypeFingerprint = new Uint32Array((id + 1) * 4);
 
         // This loop actually generates the search item indexes, including
         // normalized names, type signature objects and fingerprints, and aliases.
         id = 0;
-        for (const crate in rawSearchIndex) {
-            if (!hasOwnPropertyRustdoc(rawSearchIndex, crate)) {
-                continue;
-            }
-
-            let crateSize = 0;
-
-            /**
-             * The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
-             * are arrays with the same length. `q`, `a`, and `c` use a sparse
-             * representation for compactness.
-             *
-             * `n[i]` contains the name of an item.
-             *
-             * `t[i]` contains the type of that item
-             * (as a string of characters that represent an offset in `itemTypes`).
-             *
-             * `d[i]` contains the description of that item.
-             *
-             * `q` contains the full paths of the items. For compactness, it is a set of
-             * (index, path) pairs used to create a map. If a given index `i` is
-             * not present, this indicates "same as the last index present".
-             *
-             * `i[i]` contains an item's parent, usually a module. For compactness,
-             * it is a set of indexes into the `p` array.
-             *
-             * `f[i]` contains function signatures, or `0` if the item isn't a function.
-             * Functions are themselves encoded as arrays. The first item is a list of
-             * types representing the function's inputs, and the second list item is a list
-             * of types representing the function's output. Tuples are flattened.
-             * Types are also represented as arrays; the first item is an index into the `p`
-             * array, while the second is a list of types representing any generic parameters.
-             *
-             * b[i] contains an item's impl disambiguator. This is only present if an item
-             * is defined in an impl block and, the impl block's type has more than one associated
-             * item with the same name.
-             *
-             * `a` defines aliases with an Array of pairs: [name, offset], where `offset`
-             * points into the n/t/d/q/i/f arrays.
-             *
-             * `doc` contains the description of the crate.
-             *
-             * `p` is a list of path/type pairs. It is used for parents and function parameters.
-             *
-             * `c` is an array of item indices that are deprecated.
-             *
-             * @type {{
-             *   doc: string,
-             *   a: Object,
-             *   n: Array<string>,
-             *   t: String,
-             *   d: Array<string>,
-             *   q: Array<[Number, string]>,
-             *   i: Array<Number>,
-             *   f: Array<RawFunctionSearchType>,
-             *   p: Array<Object>,
-             *   b: Array<[Number, String]>,
-             *   c: Array<Number>
-             * }}
-             */
-            const crateCorpus = rawSearchIndex[crate];
-
+        /**
+         * The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
+         * are arrays with the same length. `q`, `a`, and `c` use a sparse
+         * representation for compactness.
+         *
+         * `n[i]` contains the name of an item.
+         *
+         * `t[i]` contains the type of that item
+         * (as a string of characters that represent an offset in `itemTypes`).
+         *
+         * `d[i]` contains the description of that item.
+         *
+         * `q` contains the full paths of the items. For compactness, it is a set of
+         * (index, path) pairs used to create a map. If a given index `i` is
+         * not present, this indicates "same as the last index present".
+         *
+         * `i[i]` contains an item's parent, usually a module. For compactness,
+         * it is a set of indexes into the `p` array.
+         *
+         * `f[i]` contains function signatures, or `0` if the item isn't a function.
+         * Functions are themselves encoded as arrays. The first item is a list of
+         * types representing the function's inputs, and the second list item is a list
+         * of types representing the function's output. Tuples are flattened.
+         * Types are also represented as arrays; the first item is an index into the `p`
+         * array, while the second is a list of types representing any generic parameters.
+         *
+         * b[i] contains an item's impl disambiguator. This is only present if an item
+         * is defined in an impl block and, the impl block's type has more than one associated
+         * item with the same name.
+         *
+         * `a` defines aliases with an Array of pairs: [name, offset], where `offset`
+         * points into the n/t/d/q/i/f arrays.
+         *
+         * `doc` contains the description of the crate.
+         *
+         * `p` is a list of path/type pairs. It is used for parents and function parameters.
+         *
+         * `c` is an array of item indices that are deprecated.
+         *
+         * @type {{
+         *   doc: string,
+         *   a: Object,
+         *   n: Array<string>,
+         *   t: String,
+         *   d: Array<string>,
+         *   q: Array<[Number, string]>,
+         *   i: Array<Number>,
+         *   f: Array<RawFunctionSearchType>,
+         *   p: Array<Object>,
+         *   b: Array<[Number, String]>,
+         *   c: Array<Number>
+         * }}
+         */
+        for (const [crate, crateCorpus] of rawSearchIndex) {
             searchWords.push(crate);
             // This object should have exactly the same set of fields as the "row"
             // object defined below. Your JavaScript runtime will thank you.
@@ -3145,14 +3129,13 @@ ${item.displayPath}<span class="${type}">${name}</span>\
                 id += 1;
                 searchIndex.push(row);
                 lastPath = row.path;
-                crateSize += 1;
             }
 
             if (aliases) {
                 const currentCrateAliases = new Map();
                 ALIASES.set(crate, currentCrateAliases);
                 for (const alias_name in aliases) {
-                    if (!hasOwnPropertyRustdoc(aliases, alias_name)) {
+                    if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) {
                         continue;
                     }
 
@@ -3168,7 +3151,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
                     }
                 }
             }
-            currentIndex += crateSize;
+            currentIndex += itemTypes.length;
         }
         return searchWords;
     }
@@ -3377,7 +3360,7 @@ if (typeof window !== "undefined") {
 } else {
     // Running in Node, not a browser. Run initSearch just to produce the
     // exports.
-    initSearch({});
+    initSearch(new Map());
 }
 
 
diff --git a/src/librustdoc/html/static/js/src-script.js b/src/librustdoc/html/static/js/src-script.js
index 679c2341f02..27b5cf1e2ae 100644
--- a/src/librustdoc/html/static/js/src-script.js
+++ b/src/librustdoc/html/static/js/src-script.js
@@ -118,10 +118,10 @@ function createSrcSidebar() {
     title.className = "title";
     title.innerText = "Files";
     sidebar.appendChild(title);
-    Object.keys(srcIndex).forEach(key => {
-        srcIndex[key][NAME_OFFSET] = key;
-        hasFoundFile = createDirEntry(srcIndex[key], sidebar, "", hasFoundFile);
-    });
+    for (const [key, source] of srcIndex) {
+        source[NAME_OFFSET] = key;
+        hasFoundFile = createDirEntry(source, sidebar, "", hasFoundFile);
+    }
 
     container.appendChild(sidebar);
     // Focus on the current file in the source files sidebar.