1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! What:
//! Text operations with the exact semantics of the JavaScript built-ins the incumbent
//! applies to strings it shares with the native wrapper.
//! Why:
//! Durable strings such as process birth identities are produced by `.trim()` in the
//! incumbent;
//! the native wrapper must produce byte-identical strings,
//! and Rust's
//! `str::trim` uses a different whitespace set (it trims U+0085 and keeps U+FEFF).
//!
//! In TS you'd write (pseudocode):
//! ```ts
//! text.trim()
//! ```
/// What:
/// Whether a character is whitespace or a line terminator to ECMAScript `trim`.
/// `char` is one Unicode scalar value.
/// Why:
/// ECMA-262 `TrimString` removes `WhiteSpace` (tab,
/// vertical tab,
/// form feed,
/// space,
/// no-break space,
/// U+FEFF and every `Zs` character) and `LineTerminator` (LF,
/// CR,
/// U+2028,
/// U+2029);
/// nothing else.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// /^\s$/u.test(character) // JavaScript's \s is exactly this set
/// ```
pub fn is_javascript_whitespace(character: char) -> bool {
// The `Zs` block U+2000 to U+200A is a range; every other member is listed.
if ('\u{2000}'..='\u{200a}').contains(&character) {
return true;
}
// `matches!` tests a value against a pattern of alternatives.
return matches!(
character,
'\u{0009}'
| '\u{000a}'
| '\u{000b}'
| '\u{000c}'
| '\u{000d}'
| '\u{0020}'
| '\u{00a0}'
| '\u{1680}'
| '\u{2028}'
| '\u{2029}'
| '\u{202f}'
| '\u{205f}'
| '\u{3000}'
| '\u{feff}'
);
}
/// What:
/// Remove leading and trailing JavaScript whitespace,
/// as `String.prototype.trim`.
/// `&str` borrows text;
/// the result borrows a slice of it.
/// Why:
/// Shared strings must be trimmed exactly as the incumbent trims them.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// function trimJavascript(text: string): string { return text.trim(); }
/// ```
pub fn trim_javascript(text: &str) -> &str {
return text.trim_matches(is_javascript_whitespace);
}
/// What:
/// Remove trailing JavaScript whitespace,
/// as `String.prototype.trimEnd`.
/// `&str` borrows text;
/// the result borrows a slice of it.
/// Why:
/// Git's PID file text is trimmed at the end only before its `pid ` prefix is read.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// function trimJavascriptEnd(text: string): string { return text.trimEnd(); }
/// ```
pub fn trim_javascript_end(text: &str) -> &str {
return text.trim_end_matches(is_javascript_whitespace);
}
/// The whitespace table stays out of the release executable.
#[cfg(test)]
#[path = "js_text_tests.rs"]
mod tests;