Skip to content

Commit f359997

Browse files
committed
Auto merge of rust-lang#118910 - GuillaumeGomez:js-object-to-map, r=<try>
[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`
2 parents 7176b8b + 7502c44 commit f359997

File tree

4 files changed

+75
-88
lines changed

4 files changed

+75
-88
lines changed

src/librustdoc/html/render/search_index.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ pub(crate) fn build_index<'tcx>(
488488

489489
// Collect the index into a string
490490
format!(
491-
r#""{}":{}"#,
491+
r#"["{}",{}]"#,
492492
krate.name(tcx),
493493
serde_json::to_string(&CrateData {
494494
doc: crate_doc,

src/librustdoc/html/render/write_shared.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -167,23 +167,24 @@ pub(super) fn write_shared(
167167
let mut krates = Vec::new();
168168

169169
if path.exists() {
170-
let prefix = format!("\"{krate}\"");
170+
let prefix = format!("[\"{krate}\"");
171171
for line in BufReader::new(File::open(path)?).lines() {
172172
let line = line?;
173-
if !line.starts_with('"') {
173+
if !line.starts_with("[\"") {
174174
continue;
175175
}
176176
if line.starts_with(&prefix) {
177177
continue;
178178
}
179-
if line.ends_with(",\\") {
179+
if line.ends_with("],\\") {
180180
ret.push(line[..line.len() - 2].to_string());
181181
} else {
182182
// Ends with "\\" (it's the case for the last added crate line)
183183
ret.push(line[..line.len() - 1].to_string());
184184
}
185185
krates.push(
186-
line.split('"')
186+
line[1..] // We skip the `[` parent at the beginning of the line.
187+
.split('"')
187188
.find(|s| !s.is_empty())
188189
.map(|s| s.to_owned())
189190
.unwrap_or_else(String::new),
@@ -285,7 +286,7 @@ pub(super) fn write_shared(
285286
let (mut all_sources, _krates) =
286287
try_err!(collect_json(&dst, krate.name(cx.tcx()).as_str()), &dst);
287288
all_sources.push(format!(
288-
r#""{}":{}"#,
289+
r#"["{}",{}]"#,
289290
&krate.name(cx.tcx()),
290291
hierarchy
291292
.to_json_string()
@@ -296,9 +297,9 @@ pub(super) fn write_shared(
296297
.replace("\\\"", "\\\\\"")
297298
));
298299
all_sources.sort();
299-
let mut v = String::from("var srcIndex = JSON.parse('{\\\n");
300+
let mut v = String::from("const srcIndex = new Map(JSON.parse('[\\\n");
300301
v.push_str(&all_sources.join(",\\\n"));
301-
v.push_str("\\\n}');\ncreateSrcSidebar();\n");
302+
v.push_str("\\\n]'));\ncreateSrcSidebar();\n");
302303
Ok(v.into_bytes())
303304
};
304305
write_invocation_specific("src-files.js", &make_sources)?;
@@ -316,11 +317,11 @@ pub(super) fn write_shared(
316317
// with rustdoc running in parallel.
317318
all_indexes.sort();
318319
write_invocation_specific("search-index.js", &|| {
319-
let mut v = String::from("var searchIndex = JSON.parse('{\\\n");
320+
let mut v = String::from("const searchIndex = new Map(JSON.parse('[\\\n");
320321
v.push_str(&all_indexes.join(",\\\n"));
321322
v.push_str(
322323
r#"\
323-
}');
324+
]'));
324325
if (typeof window !== 'undefined' && window.initSearch) {window.initSearch(searchIndex)};
325326
if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
326327
"#,

src/librustdoc/html/static/js/search.js

+60-74
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,6 @@ const longItemTypes = [
8080
const TY_GENERIC = itemTypes.indexOf("generic");
8181
const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../";
8282

83-
function hasOwnPropertyRustdoc(obj, property) {
84-
return Object.prototype.hasOwnProperty.call(obj, property);
85-
}
86-
8783
// In the search display, allows to switch between tabs.
8884
function printTab(nb) {
8985
let iter = 0;
@@ -1068,7 +1064,7 @@ function initSearch(rawSearchIndex) {
10681064

10691065
if (elem &&
10701066
elem.value !== "all crates" &&
1071-
hasOwnPropertyRustdoc(rawSearchIndex, elem.value)
1067+
rawSearchIndex.has(elem.value)
10721068
) {
10731069
return elem.value;
10741070
}
@@ -2552,11 +2548,10 @@ ${item.displayPath}<span class="${type}">${name}</span>\
25522548
}
25532549

25542550
let crates = "";
2555-
const crates_list = Object.keys(rawSearchIndex);
2556-
if (crates_list.length > 1) {
2551+
if (rawSearchIndex.size > 1) {
25572552
crates = " in&nbsp;<div id=\"crate-search-div\"><select id=\"crate-search\">" +
25582553
"<option value=\"all crates\">all crates</option>";
2559-
for (const c of crates_list) {
2554+
for (const c of rawSearchIndex.keys()) {
25602555
crates += `<option value="${c}" ${c === filterCrates && "selected"}>${c}</option>`;
25612556
}
25622557
crates += "</select></div>";
@@ -2859,68 +2854,60 @@ ${item.displayPath}<span class="${type}">${name}</span>\
28592854
typeNameIdOfSlice = buildTypeMapIndex("slice");
28602855
typeNameIdOfArrayOrSlice = buildTypeMapIndex("[]");
28612856

2862-
for (const crate in rawSearchIndex) {
2863-
if (!hasOwnPropertyRustdoc(rawSearchIndex, crate)) {
2864-
continue;
2865-
}
2866-
2867-
let crateSize = 0;
2868-
2869-
/**
2870-
* The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
2871-
* are arrays with the same length. `q`, `a`, and `c` use a sparse
2872-
* representation for compactness.
2873-
*
2874-
* `n[i]` contains the name of an item.
2875-
*
2876-
* `t[i]` contains the type of that item
2877-
* (as a string of characters that represent an offset in `itemTypes`).
2878-
*
2879-
* `d[i]` contains the description of that item.
2880-
*
2881-
* `q` contains the full paths of the items. For compactness, it is a set of
2882-
* (index, path) pairs used to create a map. If a given index `i` is
2883-
* not present, this indicates "same as the last index present".
2884-
*
2885-
* `i[i]` contains an item's parent, usually a module. For compactness,
2886-
* it is a set of indexes into the `p` array.
2887-
*
2888-
* `f[i]` contains function signatures, or `0` if the item isn't a function.
2889-
* Functions are themselves encoded as arrays. The first item is a list of
2890-
* types representing the function's inputs, and the second list item is a list
2891-
* of types representing the function's output. Tuples are flattened.
2892-
* Types are also represented as arrays; the first item is an index into the `p`
2893-
* array, while the second is a list of types representing any generic parameters.
2894-
*
2895-
* b[i] contains an item's impl disambiguator. This is only present if an item
2896-
* is defined in an impl block and, the impl block's type has more than one associated
2897-
* item with the same name.
2898-
*
2899-
* `a` defines aliases with an Array of pairs: [name, offset], where `offset`
2900-
* points into the n/t/d/q/i/f arrays.
2901-
*
2902-
* `doc` contains the description of the crate.
2903-
*
2904-
* `p` is a list of path/type pairs. It is used for parents and function parameters.
2905-
*
2906-
* `c` is an array of item indices that are deprecated.
2907-
*
2908-
* @type {{
2909-
* doc: string,
2910-
* a: Object,
2911-
* n: Array<string>,
2912-
* t: String,
2913-
* d: Array<string>,
2914-
* q: Array<[Number, string]>,
2915-
* i: Array<Number>,
2916-
* f: Array<RawFunctionSearchType>,
2917-
* p: Array<Object>,
2918-
* b: Array<[Number, String]>,
2919-
* c: Array<Number>
2920-
* }}
2921-
*/
2922-
const crateCorpus = rawSearchIndex[crate];
2923-
2857+
/**
2858+
* The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
2859+
* are arrays with the same length. `q`, `a`, and `c` use a sparse
2860+
* representation for compactness.
2861+
*
2862+
* `n[i]` contains the name of an item.
2863+
*
2864+
* `t[i]` contains the type of that item
2865+
* (as a string of characters that represent an offset in `itemTypes`).
2866+
*
2867+
* `d[i]` contains the description of that item.
2868+
*
2869+
* `q` contains the full paths of the items. For compactness, it is a set of
2870+
* (index, path) pairs used to create a map. If a given index `i` is
2871+
* not present, this indicates "same as the last index present".
2872+
*
2873+
* `i[i]` contains an item's parent, usually a module. For compactness,
2874+
* it is a set of indexes into the `p` array.
2875+
*
2876+
* `f[i]` contains function signatures, or `0` if the item isn't a function.
2877+
* Functions are themselves encoded as arrays. The first item is a list of
2878+
* types representing the function's inputs, and the second list item is a list
2879+
* of types representing the function's output. Tuples are flattened.
2880+
* Types are also represented as arrays; the first item is an index into the `p`
2881+
* array, while the second is a list of types representing any generic parameters.
2882+
*
2883+
* b[i] contains an item's impl disambiguator. This is only present if an item
2884+
* is defined in an impl block and, the impl block's type has more than one associated
2885+
* item with the same name.
2886+
*
2887+
* `a` defines aliases with an Array of pairs: [name, offset], where `offset`
2888+
* points into the n/t/d/q/i/f arrays.
2889+
*
2890+
* `doc` contains the description of the crate.
2891+
*
2892+
* `p` is a list of path/type pairs. It is used for parents and function parameters.
2893+
*
2894+
* `c` is an array of item indices that are deprecated.
2895+
*
2896+
* @type {{
2897+
* doc: string,
2898+
* a: Object,
2899+
* n: Array<string>,
2900+
* t: String,
2901+
* d: Array<string>,
2902+
* q: Array<[Number, string]>,
2903+
* i: Array<Number>,
2904+
* f: Array<RawFunctionSearchType>,
2905+
* p: Array<Object>,
2906+
* b: Array<[Number, String]>,
2907+
* c: Array<Number>
2908+
* }}
2909+
*/
2910+
for (const [crate, crateCorpus] of rawSearchIndex) {
29242911
searchWords.push(crate);
29252912
// This object should have exactly the same set of fields as the "row"
29262913
// object defined below. Your JavaScript runtime will thank you.
@@ -3027,14 +3014,13 @@ ${item.displayPath}<span class="${type}">${name}</span>\
30273014
id += 1;
30283015
searchIndex.push(row);
30293016
lastPath = row.path;
3030-
crateSize += 1;
30313017
}
30323018

30333019
if (aliases) {
30343020
const currentCrateAliases = new Map();
30353021
ALIASES.set(crate, currentCrateAliases);
30363022
for (const alias_name in aliases) {
3037-
if (!hasOwnPropertyRustdoc(aliases, alias_name)) {
3023+
if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) {
30383024
continue;
30393025
}
30403026

@@ -3050,7 +3036,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
30503036
}
30513037
}
30523038
}
3053-
currentIndex += crateSize;
3039+
currentIndex += itemTypes.length;
30543040
}
30553041
return searchWords;
30563042
}
@@ -3259,7 +3245,7 @@ if (typeof window !== "undefined") {
32593245
} else {
32603246
// Running in Node, not a browser. Run initSearch just to produce the
32613247
// exports.
3262-
initSearch({});
3248+
initSearch(new Map());
32633249
}
32643250

32653251

src/librustdoc/html/static/js/src-script.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@ function createSrcSidebar() {
118118
title.className = "title";
119119
title.innerText = "Files";
120120
sidebar.appendChild(title);
121-
Object.keys(srcIndex).forEach(key => {
122-
srcIndex[key][NAME_OFFSET] = key;
123-
hasFoundFile = createDirEntry(srcIndex[key], sidebar, "", hasFoundFile);
124-
});
121+
for (const [key, source] of srcIndex) {
122+
source[NAME_OFFSET] = key;
123+
hasFoundFile = createDirEntry(source, sidebar, "", hasFoundFile);
124+
}
125125

126126
container.appendChild(sidebar);
127127
// Focus on the current file in the source files sidebar.

0 commit comments

Comments
 (0)