forked from whatwg/infra
-
Notifications
You must be signed in to change notification settings - Fork 0
/
infra.bs
2070 lines (1478 loc) · 90.7 KB
/
infra.bs
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class=metadata>
Group: WHATWG
H1: Infra
Shortname: infra
Text Macro: TWITTER infrastandard
Text Macro: LATESTRD 2023-07
Abstract: The Infra Standard aims to define the fundamental concepts upon which standards are built.
Translation: ja https://triple-underscore.github.io/infra-ja.html
Required IDs: tracking-vector
</pre>
<pre class=anchors>
urlPrefix: https://tc39.github.io/ecma262/#; spec: ECMA-262;
type: dfn
text: %JSON.parse%; url: sec-json.parse
text: %JSON.stringify%; url: sec-json.stringify
text: List; url: sec-list-and-record-specification-type
text: The String Type; url: sec-ecmascript-language-types-string-type
text: realm; url: realm
type: method; for: Array; text: sort(); url: sec-array.prototype.sort
type: abstract-op;
text: ArrayCreate; url: sec-arraycreate
text: Call; url: sec-call
text: CreateDataPropertyOrThrow; url: sec-createdatapropertyorthrow
text: Get; url: sec-get-o-p
text: IsArray; url: sec-isarray
text: OrdinaryObjectCreate; url: sec-ordinaryobjectcreate
text: ToLength; url: sec-tolength
text: ToString; url: sec-tostring
text: Type; url: sec-ecmascript-data-types-and-values
</pre>
<style>
/* Used for normative exemplars of how to write algorithms, as distinct from .example */
.exemplary-prose {
margin-left: 2em;
}
</style>
<h2 id=goals class=no-num>Goals</h2>
<ul>
<li><p>Deduplicate boilerplate in standards.
<li><p>Align standards on conventions, terminology, and data structures.
<li><p>Be a place for concepts used by multiple standards without a good home.
<li><p>Help write clear and readable algorithmic prose by clarifying otherwise ambiguous concepts.
</ul>
<p>Suggestions for more goals welcome.</p>
<h2 id=usage>Usage</h2>
<p>To make use of this standard in a document titled <var>X</var>, use:
<p><samp><var>X</var> depends on <cite>Infra</cite>. [[!Infra]]</samp>
<!-- Yo Dawg -->
<p>Additionally, cross-referencing all terminology is strongly encouraged to avoid ambiguity.
<h2 id=conventions>Conventions</h2>
<h3 id=conformance>Conformance</h3>
<p>All assertions, diagrams, examples, and notes are non-normative, as are all sections explicitly
marked non-normative. Everything else is normative.
<p>The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
"RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as described in
RFC 2119. [[!RFC2119]]
<p>These keywords have equivalent meaning when written in lowercase and cannot appear in
non-normative content.
<p class=note>This is a <a>willful violation</a> of RFC 8174, motivated by legibility and a desire
to preserve long-standing practice in many non-IETF-published pre-RFC 8174 documents. [[RFC8174]]
<p>All of the above is applicable to both this standard and any document that uses this standard.
Documents using this standard are encouraged to limit themselves to "must", "must not", "should",
and "may", and to use these in their lowercase form as that is generally considered to be more
readable.
<p>For non-normative content "strongly encouraged", "strongly discouraged", "encouraged",
"discouraged", "can", "cannot", "could", "could not", "might", and "might not" can be used instead.
<h3 id=other-specs>Compliance with other specifications</h3>
<p>In general, specifications interact with and rely on a wide variety of other specifications. In
certain circumstances, unfortunately, conflicting needs require a specification to violate the
requirements of other specifications. When this occurs, a document using the Infra Standard should
denote such transgressions as a <dfn export>willful violation</dfn>, and note the reason for that
violation.
<p class=example id=example-willful-violation>The previous section, [[#conformance]], documents a
<a>willful violation</a> of RFC 8174 committed by <cite>Infra</cite>.
<h3 id=terminology>Terminology</h3>
<p>The word "or", in cases where both inclusive "or" and exclusive "or" are possible (e.g., "if
either width or height is zero"), means an inclusive "or" (implying "or both"), unless it is called
out as being exclusive (with "but not both").
<hr>
<p>A <dfn export>user agent</dfn> is any software entity that acts on behalf
of a user, for example by retrieving and rendering web content and facilitating end user interaction
with it. In specifications using the Infra Standard, the user agent is generally an instance of the client software
that implements the specification. The client software itself is known as an <dfn export>implementation</dfn>.
A person can use many different [=user agents=] in their day-to-day life, including by configuring an
[=implementation=] to act as several [=user agents=] at once, for example by using multiple profiles
or the implementation's private browsing mode.
<p>If something is said to be <dfn export>implementation-defined</dfn>, the particulars of what is
said to be <a>implementation-defined</a> are up to the <a>implementation</a>. In the absence of such
language, the reverse holds: <a>implementations</a> have to follow the rules laid out in documents using
this standard.
<p class="example" id=example-implementation-defined>Insert U+000A (LF) code points into
<var ignore>input</var> in an <a>implementation-defined</a> manner such that each resulting line has
no more than <var ignore>width</var> code points. For the purposes of this requirement, lines are
delimited by the start of <var ignore>input</var>, the end of <var ignore>input</var>, and
U+000A (LF).
<h3 id=privacy>Privacy concerns</h3>
<p>Some features that are defined in documents using the Infra Standard might trade user convenience
for a measure of user privacy.
<p>In general, due to the internet's architecture, a user can be distinguished from another by the
user's IP address. IP addresses do not perfectly match to a user; as a user moves from device to
device, or from network to network, their IP address will change; similarly, NAT routing, proxy
servers, and shared computers enable packets that appear to all come from a single IP address to
actually map to multiple users. Technologies such as onion routing can be used to further anonymize
requests so that requests from a single user at one node on the internet appear to come from many
disparate parts of the network. [[RFC791]]
<p>However, the IP address used for a user's requests is not the only mechanism by which a user's
requests could be related to each other. Cookies, for example, are designed specifically to enable
this, and are the basis of most of the web's session features that enable you to log into a site
with which you have an account. More generally, any kind of cache mechanism or shared state,
including but not limited to HSTS, the HTTP cache, grouping of connections, storage APIs, can and
ought to be expected to be abused. [[COOKIES]] [[RFC6797]] [[STORAGE]]
<p>There are other mechanisms that are more subtle. Certain characteristics of a user's system can
be used to distinguish groups of users from each other. By collecting enough such information, an
individual user's browser's "digital fingerprint" can be computed, which can be better than an IP
address in ascertaining which requests are from the same user.
<p>Grouping requests in this manner, especially across multiple sites, can be used for malevolent
purposes, e.g., governments combining information such as the person's home address (determined from
the addresses they use when getting driving directions on one site) with their apparent political
affiliations (determined by examining the forum sites that they participate in) to determine whether
the person should be prevented from voting in an election.
<p>Since the malevolent purposes can be remarkably evil, user agent implementors and specification
authors are strongly encouraged to minimize leaking information that could be used to fingerprint or
track a user.
<p>Unfortunately, as the first paragraph in this section implies, sometimes there is great benefit
to be derived from exposing APIs that can also be abused for fingerprinting and tracking purposes,
so it's not as easy as blocking all possible leaks. For instance, the ability to log into a site to
post under a specific identity requires that the user's requests be identifiable as all being from
the same user, more or less by definition. More subtly, though, information such as how wide text
is, which is necessary for many effects that involve drawing text onto a canvas (e.g., any effect
that involves drawing a border around the text) also leaks information that can be used to group a
user's requests. (In this case, by potentially exposing, via a brute force search, which fonts a
user has installed, information which can vary considerably from user to user.)
<p tracking-vector>Features that are defined in documents using the Infra Standard that can be used
as a <dfn export>tracking vector</dfn> are marked as this paragraph is.
<p>Other features in the platform can be used for the same purpose, including, but not limited to:
<ul>
<li>The exact list of which features a user agents supports.
<li>The maximum allowed stack depth for recursion in script.
<li>Features that describe the user's environment.
<li>The user's time zone.
<li>HTTP request headers.
</ul>
<h2 id=algorithms>Algorithms</h2>
<h3 id=algorithm-conformance>Conformance</h3>
<p>Algorithms, and requirements phrased in the imperative as part of algorithms (such as "strip any
leading spaces" or "return false") are to be interpreted with the meaning of the keyword (e.g.,
"must") used in introducing the algorithm or step. If no such keyword is used, must is implied.
<div class=example id=example-algorithms>
<p>For example, were the spec to say:</p>
<div class=exemplary-prose>
<p class=allow-2119>To <dfn ignore>eat an orange</dfn>, the user must:
<ol class=brief>
<li>Peel the orange.
<li>Separate each slice of the orange.
<li>Eat the orange slices.
</ol>
</div>
<p>it would be equivalent to the following:</p>
<div class=exemplary-prose>
<p>To <dfn ignore>eat an orange</dfn>:
<ol class=brief>
<li class=allow-2119>The user must peel the orange.
<li class=allow-2119>The user must separate each slice of the orange.
<li class=allow-2119>The user must eat the orange slices.
</ol>
</div>
<p class=allow-2119>Here the key word is "must".</p>
<p class=allow-2119>Modifying the above example, if the algorithm was introduced only with "To eat
an orange:", it would still have the same meaning, as "must" is implied.
</div>
<p>Conformance requirements phrased as algorithms or specific steps may be implemented in any
manner, so long as the end result is equivalent. (In particular, the algorithms are intended to be
easy to follow, and not intended to be performant.)
<p class=note>Performance is tricky to get correct as it is influenced by user perception, computer
architectures, and different types of input that can change over time in how common they are. For
instance, a JavaScript engine likely has many different code paths for what is standardized as a
single algorithm, in order to optimize for speed or memory consumption. Standardizing all those code
paths would be an insurmountable task and not productive as they would not stand the test of time
as well as the single algorithm would. Therefore performance is best left as a field to compete
over.
<h3 id=algorithm-limits>Avoid limits on algorithm inputs</h3>
<p>A document using the Infra Standard generally should not enforce specific limits on algorithm
inputs with regards to their size, resource usage, or equivalent. This allows for competition among
user agents and avoids constraining the potential computing needs of the future.
<p tracking-vector>Nevertheless, user agents may impose <a>implementation-defined</a> limits on
otherwise unconstrained inputs. E.g., to prevent denial of service attacks, to guard against running
out of memory, or to work around platform-specific limitations.
<p class=note>Global resource limits can be used as side channels through a variant on a resource
exhaustion attack, whereby the attacker can observe whether a victim application reaches the global
limit. Limits could also be used to fingerprint the user agent, but only if they make the user agent
more unique in some manner, e.g., if they are specific to the underlying hardware.
<p class=example id=example-algorithm-limits>An API that allows creating an in-memory bitmap might
be specified to allow any dimensions, or any dimensions up to some large limit like JavaScript's
<code>Number.MAX_SAFE_INTEGER</code>. However, implementations can choose to impose some
<a>implementation-defined</a> (and thus not specified) limit on the dimensions, instead of
attempting to allocate huge amounts of memory.
<p class=example id=example-algorithm-limits-language>A programming language might not have a
maximum call stack size specified. However, implementations could choose to impose one for practical
reasons.
<p>As code can end up depending on a particular limit, it can be useful to define a limit for
interoperability. Sometimes, embracing that is not problematic for the future, and can make the code
run in more user agents.
<p>It can also be useful to constrain an <a>implementation-defined</a> limit with a lower limit.
I.e., ensuring all implementations can handle inputs of a given minimum size.
<h3 id=algorithm-declaration>Declaration</h3>
<p>Algorithm names are usually verb phrases, but sometimes are given names that emphasize their
standalone existence, so that standards and readers can refer to the algorithm more idiomatically.
<p class=example id=example-algorithm-declaration-names>Some algorithm names in the latter category
include "attribute change steps", "internal module script graph fetching procedure", and "overload
resolution algorithm".
<p>Declare algorithms by stating their name, parameters, and return type, in the following form:
<p class=exemplary-prose>To <dfn ignore>[algorithm name]</dfn>, given a [type1]
<var ignore>[parameter1]</var>, a [type2] <var ignore>[parameter2]</var>, …, perform the
following steps. They return a [return type].</p>
<p>(For non-verb phrase algorithm names, use "To perform the
<dfn ignore>[algorithm name]</dfn>…". See also [[#algorithm-params]] for more complicated
parameter-declaration forms.)
<p class=example id=example-algorithm-declaration>To <dfn ignore>parse an awesome format</dfn> given
a [=byte sequence=] <var ignore>bytes</var>, perform the following steps. They return a
[=string=] or null.
<p>Algorithms which do not return a value use a shorter form. This same shorter form can be used even
for algorithms that do return a value if the return type is relatively easy to infer from the
algorithm steps:
<p class=exemplary-prose>To <dfn ignore>[algorithm name]</dfn>, given a [type1]
<var ignore>[parameter1]</var>, a [type2] <var ignore>[parameter2]</var>, …:</p>
<p class=example id=example-algorithm-declaration-no-return>To
<dfn ignore>parse an awesome format</dfn> given a [=byte sequence=] <var ignore>bytes</var>:
<p>Very short algorithms can be declared and specified using a single sentence:
<p class=example id=example-algorithm-declaration-short>To <dfn ignore>parse an awesome format</dfn>
given a [=byte sequence=] <var ignore>bytes</var>, return the result of
<a lt="ASCII uppercase">ASCII uppercasing</a> the <a lt="isomorphic decode">isomorphic decoding</a>
of <var ignore>bytes</var>.
<p>Types should be included in algorithm declarations, but may be omitted if the parameter name is
clear enough, or if they are otherwise clear from context. (For example, because the algorithm is
a simple wrapper around another one.)
<p class=example id=example-algorithm-declaration-no-types>To
<dfn ignore>load a classic script</dfn> given <var>url</var>, return the result of performing the
internal script-loading algorithm given <var>url</var> and "<code>classic</code>".
<h3 id=algorithm-params>Parameters</h3>
<p>Algorithm parameters are usually listed sequentially, in the fashion described in
[[#algorithm-declaration]]. However, there are some more complicated cases.</p>
<p>Algorithm parameters can be optional, in which case the algorithm declaration must list them as
such, and list them after any non-optional parameters. They can either be given a default value, or
the algorithm body can check whether or not the argument was given. Concretely, use the following
forms:
<p class=exemplary-prose>… an optional [type] <var ignore>[parameter]</var> …
<p class=exemplary-prose>… an optional [type] <var ignore>[parameter]</var> (default [default
value]) …
<p>Optional <a>boolean</a> parameters must have a default value specified, and that default must be
false.
<div class=example id=example-algorithm-optional-positional-params>
<p class=allow-2119>To <dfn ignore id=example-navigate-algo-positional>navigate</dfn> to a
resource <var ignore>resource</var>, with an optional string <var ignore>navigationType</var> and
an optional boolean <var ignore>exceptionsEnabled</var> (default false):
<ol class=brief>
<li>…
<li>If <var ignore>navigationType</var> was given, then do something with
<var ignore>navigationType</var>.
<li>…
</ol>
</div>
<p>To call algorithms with such optional positional parameters, the optional argument values can be
omitted, but only the trailing ones.
<div class=example id=example-algorithm-optional-positional-params-calling>
<p>Call sites to the previous example's algorithm would look like one of:
<ul class=brief>
<li><a href=#example-navigate-algo-positional>Navigate</a> to <var ignore>resource</var>.
<li><a href=#example-navigate-algo-positional>Navigate</a> to <var ignore>resource</var> with
"<code>form submission</code>".
<li><a href=#example-navigate-algo-positional>Navigate</a> to <var ignore>resource</var> with
"<code>form submission</code>" and true.
</ul>
<p>But, there would be no way to supply a non-default value for the third
(<var ignore>exceptionsEnabled</var>) argument, while leaving the second
(<var ignore>navigationType</var>) argument as not-given. Additionally, the last of these calls is
fairly unclear for readers, as the fact that "true" means "exceptions enabled" requires going back
to the algorithm's declaration and counting parameters. Read on for how to fix these issues!
</div>
<p>Optional named parameters, instead of positional ones, can be used to increase clarity and
flexibility at the call site. Such parameters are marked up as both variables and definitions, and
linked to from their call sites.
<div class=example id=example-algorithm-optional-named-params>
<p class=allow-2119>To <dfn ignore id=example-navigate-algo-named>navigate</dfn> to a
resource <var ignore>resource</var>, with an optional string
<dfn ignore id=example-navigate-algo-navigationType><var ignore>navigationType</var></dfn> and an
optional boolean
<dfn ignore id=example-navigate-algo-exceptionsEnabled><var ignore>exceptionsEnabled</var></dfn>
(default false):
<ol class=brief>
<li>…
<li>If <var ignore>navigationType</var> was given, then do something with
<var ignore>navigationType</var>.
<li>…
</ol>
<p>Call sites would then look like one of:
<ul class=brief>
<li><a href=#example-navigate-algo-named>Navigate</a> to <var ignore>resource</var>.
<li><a href=#example-navigate-algo-named>Navigate</a> to <var ignore>resource</var> with
<a href=#example-navigate-algo-navigationType><i>navigationType</i></a> set to
"<code>form-submission</code>".
<li><a href=#example-navigate-algo-named>Navigate</a> to <var ignore>resource</var> with
<a href=#example-navigate-algo-exceptionsEnabled><i>exceptionsEnabled</i></a> set to true.
<li><a href=#example-navigate-algo-named>Navigate</a> to <var ignore>resource</var> with
<a href=#example-navigate-algo-navigationType><i>navigationType</i></a> set to
"<code>form-submission</code>" and
<a href=#example-navigate-algo-exceptionsEnabled><i>exceptionsEnabled</i></a> set to
true.
</ul>
</div>
<p class=note>Note how within the algorithm steps, the argument value is not linked to the parameter
declaration; it remains just a variable reference. Linking to the parameter declaration is done only
at the call sites.
<p>Non-optional named parameters may also be used, using the same convention of marking them up as
both variables and definitions, and linking to them from call sites. This can improve clarity at the
call sites.
<p class="example allow-2119" id=example-algorithm-non-optional-named-params><a>Boolean</a>
parameters are a case where naming the parameter can be significantly clearer than leaving it as
positional, regardless of optionality. See
<a href="https://ariya.io/2011/08/hall-of-api-shame-boolean-trap"><cite>The Pitfalls of Boolean
Trap</cite></a> for discussion of this in the context of programming languages.
<p>Another complementary technique for improving clarity is to package up related values into a
<a>struct</a>, and pass that struct as a parameter. This is especially applicable when the same set
of related values is used as the input to multiple algorithms.
<h3 id=variables>Variables</h3>
<p>A variable is declared with "let" and changed with "set".
<p class=example id=example-variable>Let |list| be a new <a>list</a>.</p>
<div class=example id=example-variable-null>
<ol>
<li><p>Let |value| be null.
<li><p>If |input| is a <a>string</a>, then set |value| to |input|.
<li><p>Otherwise, set |value| to |input|, <a>UTF-8 decoded</a>.
<li><p><a>Assert</a>: |value| is a <a>string</a>.
</ol>
</div>
<p class=example id=example-variable-ternary>Let <var ignore>activationTarget</var> be
<var ignore>target</var> if <var ignore>isActivationEvent</var> is true and target has activation
behavior; otherwise null.
<p>Variables must not be used before they are declared. Variables are
<a href=https://en.wikipedia.org/wiki/Scope_(computer_science)#Block_scope>block scoped</a>.
Variables must not be declared more than once per algorithm.
<p>A multiple assignment syntax can be used to assign multiple variables to the <a>tuple</a>'s
<a for=tuple>items</a>, by surrounding the variable names with parenthesis and separating each
variable name by a comma. The number of variables assigned cannot differ from the number of
<a for=tuple>items</a> in the <a>tuple</a>.
<div class=example id=example-tuple-multiple-assignment>
<ol>
<li><p>Let |statusInstance| be the status (200, `<code>OK</code>`).
<li><p>Let (|status|, |statusMessage|) be |statusInstance|.
</ol>
<p>Assigning |status| and |statusMessage| could be written as two separate steps that use an index
or <a for=tuple>name</a> to access the <a>tuple</a>'s <a for=tuple>items</a>.
</div>
<h3 id=algorithm-control-flow>Control flow</h3>
<p>The control flow of algorithms is such that a requirement to "return" or "throw" terminates the
algorithm the statement was in. "Return" will hand the given value, if any, to its caller. "Throw"
will make the caller automatically rethrow the given value, if any, and thereby terminate the
caller's algorithm. Using prose the caller has the ability to "catch" the exception and perform
another action.
<h3 id=algorithm-conditional-abort>Conditional abort</h3>
<p>Sometimes it is useful to stop performing a series of steps once a condition becomes true.
<p>To do this, state that a given series of steps will <dfn export>abort when</dfn> a specific
<var>condition</var> is reached. This indicates that the specified steps must be evaluated, not
as-written, but by additionally inserting a step before each of them that evaluates
<var>condition</var>, and if <var>condition</var> evaluates to true, skips the remaining steps.
<p>In such algorithms, the subsequent step can be annotated to run <dfn export>if aborted</dfn>, in
which case it must run if any of the preceding steps were skipped due to the <var>condition</var>
of the preceding <a>abort when</a> step evaluated to true.
<div class=example id=example-conditional-abort>
<p>The following algorithm
<ol>
<li><p>Let |result| be an empty <a>list</a>.
<li>
<p>Run these steps, but <a>abort when</a> the user clicks the "Cancel" button:
<ol>
<li><p>Compute the first million digits of <var>π</var>, and <a for=list>append</a> the result
to |result|.
<li><p>Compute the first million digits of |e|, and <a for=list>append</a> the result to
|result|.
<li><p>Compute the first million digits of <var>φ</var>, and <a for=list>append</a> the result
to |result|.
</ol>
</li>
<li><p><a>If aborted</a>, <a for=list>append</a> "<code>Didn't finish!</code>" to |result|.
</ol>
<p>is equivalent to the more verbose formulation</p>
<ol>
<li><p>Let |result| be an empty <a>list</a>.
<li>
<p>If the user has not clicked the "Cancel" button, then:
<ol>
<li><p>Compute the first million digits of <var>π</var>, and <a for=list>append</a> the result
to |result|.
<li>
<p>If the user has not clicked the "Cancel" button, then:
<ol>
<li><p>Compute the first million digits of |e|, and <a for=list>append</a> the result to
|result|.
<li><p>If the user has not clicked the "Cancel" button, then compute the first million digits
of <var>φ</var>, and <a for=list>append</a> the result to |result|.
</ol>
</ol>
<li><p>If the user clicked the "Cancel" button, then <a for=list>append</a>
"<code>Didn't finish!</code>" to |result|.
</ol>
</div>
<p class=note>Whenever this construct is used, implementations are allowed to evaluate
<var>condition</var> during the specified steps rather than before and after each step, as long as
the end result is indistinguishable. For instance, as long as |result| in the above example is not
mutated during a compute operation, the user agent could stop the computation.
<h3 id=algorithm-iteration>Iteration</h3>
<p>There's a variety of ways to repeat a set of steps until a condition is reached.
<p class=note>The Infra Standard is not (yet) exhaustive on this; please file an issue if you need
something.
<dl>
<dt>For each
<dd><p>As defined for <a for=list lt="for each">lists</a> (and derivatives) and
<a for=map lt="for each">maps</a>.
<dt><dfn export for=iteration lt=while>While</dfn>
<dd>
<p>An instruction to repeat a set of steps as long as a condition is met.
<div class=example id=example-while>
<p>While |condition| is "<code>met</code>":
<ol>
<li><p>…
</ol>
</div>
</dl>
<p>An iteration's flow can be controlled via requirements to
<dfn export for=iteration>continue</dfn> or <dfn export for=iteration>break</dfn>.
<a for=iteration>Continue</a> will skip over any remaining steps in an iteration, proceeding to the
next item. If no further items remain, the iteration will stop. <a for=iteration>Break</a> will skip
over any remaining steps in an iteration, and skip over any remaining items as well, stopping the
iteration.
<div class=example id=example-break-continue>
<p>Let |example| be the <a>list</a> « 1, 2, 3, 4 ». The following prose would perform |operation|
upon 1, then 2, then 3, then 4:
<ol>
<li>
<p><a for=list>For each</a> |item| of |example|:
<ol>
<li>Perform |operation| on |item|.
</ol>
</li>
</ol>
<p>The following prose would perform |operation| upon 1, then 2, then 4. 3 would be skipped.
<ol>
<li>
<p><a for=list>For each</a> |item| of |example|:
<ol>
<li>If |item| is 3, then <a for=iteration>continue</a>.
<li>Perform |operation| on |item|.
</ol>
</li>
</ol>
<p>The following prose would perform |operation| upon 1, then 2. 3 and 4 would be skipped.
<ol>
<li>
<p><a for=list>For each</a> |item| of |example|:
<ol>
<li>If |item| is 3, then <a for=iteration>break</a>.
<li>Perform |operation| on |item|.
</ol>
</li>
</ol>
</div>
<h3 id=assertions>Assertions</h3>
<p>To improve readability, it can sometimes help to add assertions to algorithms, stating
invariants. To do this, write "<dfn export>Assert</dfn>:", followed by a statement that must be
true. If the statement ends up being false that indicates an issue with the document using the Infra
Standard that should be reported and addressed.
<p class=note>Since the statement can only ever be true, it has no implications for implementations.
<div class=example id=example-assert>
<ol>
<li><p>Let |x| be "<code>Aperture Science</code>".
<li><p><a>Assert</a>: |x| is "<code>Aperture Science</code>".
</div>
<h2 id=primitive-data-types>Primitive data types</h2>
<h3 id=nulls>Nulls</h3>
<p>The value null is used to indicate the lack of a value. It can be used interchangeably with the
JavaScript <b>null</b> value. [[!ECMA-262]]
<p class=example id=example-null>Let <var ignore>element</var> be null.
<p class=example id=example-null-return>If <var>input</var> is the empty string, then return null.
<h3 id=booleans>Booleans</h3>
<p>A <dfn export>boolean</dfn> is either true or false.
<p class=example id=example-boolean>Let <var ignore>elementSeen</var> be false.
<h3 id=bytes>Bytes</h3>
<p>A <dfn export>byte</dfn> is a sequence of eight bits and is represented as "<code>0x</code>"
followed by two <a>ASCII upper hex digits</a>, in the range 0x00 to 0xFF, inclusive. A <a>byte</a>'s
<dfn export for=byte>value</dfn> is its underlying number.
<p class=example id=example-byte-value>0x40 is a <a>byte</a> whose <a for=byte>value</a> is 64.
<p>An <dfn export>ASCII byte</dfn> is a <a>byte</a> in the range 0x00 (NUL) to 0x7F (DEL),
inclusive. As illustrated, an <a>ASCII byte</a>, excluding 0x28 and 0x29, may be followed by the
representation outlined in the <a href=https://tools.ietf.org/html/rfc20#section-2>Standard Code</a>
section of <cite>ASCII format for Network Interchange</cite>, between parentheses. [[!RFC20]]
<p>0x28 may be followed by "(left parenthesis)" and 0x29 by "(right parenthesis)".
<p class=example id=example-byte-notation>0x49 (I) when <a>UTF-8 decoded</a> becomes the
<a>code point</a> U+0049 (I).
<h3 id=byte-sequences>Byte sequences</h3>
<p>A <dfn export>byte sequence</dfn> is a sequence of <a>bytes</a>, represented as a space-separated
sequence of bytes. Byte sequences with bytes in the range 0x20 (SP) to 0x7E (~), inclusive, can
alternately be written as a string, but using backticks instead of quotation marks, to avoid
confusion with an actual <a>string</a>.
<div class=example id=example-byte-sequence-notation>
<p>0x48 0x49 can also be represented as `<code>HI</code>`.
<p>Headers, such as `<code>Content-Type</code>`, are <a>byte sequences</a>.
</div>
<p class=note>To get a <a>byte sequence</a> out of a <a>string</a>, using <a>UTF-8 encode</a> from
<cite>Encoding</cite> is encouraged. In rare circumstances <a>isomorphic encode</a> might be needed.
[[ENCODING]]
<p>A <a>byte sequence</a>'s <dfn export for="byte sequence">length</dfn> is the number of
<a>bytes</a> it contains.
<p>To <dfn export>byte-lowercase</dfn> a <a>byte sequence</a>, increase each <a>byte</a> it
contains, in the range 0x41 (A) to 0x5A (Z), inclusive, by 0x20.
<p>To <dfn export>byte-uppercase</dfn> a <a>byte sequence</a>, subtract each <a>byte</a> it
contains, in the range 0x61 (a) to 0x7A (z), inclusive, by 0x20.
<p>A <a>byte sequence</a> <var>A</var> is a <dfn export>byte-case-insensitive</dfn> match for a
<a>byte sequence</a> <var>B</var>, if the <a>byte-lowercase</a> of <var>A</var> is the
<a>byte-lowercase</a> of <var>B</var>.
<hr>
<p>A <a>byte sequence</a> <var>potentialPrefix</var> is a
<dfn export for="byte sequence">prefix</dfn> of a <a>byte sequence</a> <var>input</var> if the
following steps return true:
<ol>
<li><p>Let <var>i</var> be 0.
<li>
<p><a>While</a> true:
<ol>
<li><p>If <var>i</var> is greater than or equal to <var>potentialPrefix</var>'s
<a for="byte sequence">length</a>, then return true.
<li><p>If <var>i</var> is greater than or equal to <var>input</var>'s
<a for="byte sequence">length</a>, then return false.
<li><p>Let <var>potentialPrefixByte</var> be the <var>i</var>th <a>byte</a> of
<var>potentialPrefix</var>.
<li><p>Let <var>inputByte</var> be the <var>i</var>th <a>byte</a> of <var>input</var>.
<li><p>Return false if <var>potentialPrefixByte</var> is not <var>inputByte</var>.
<li><p>Set <var>i</var> to <var>i</var> + 1.
</ol>
</li>
</ol>
<p>"<var>input</var> <dfn export for="byte sequence" lt="starts with|start with">starts with</dfn>
<var>potentialPrefix</var>" can be used as a synonym for "<var>potentialPrefix</var> is a
<a for="byte sequence">prefix</a> of <var>input</var>".
<p>A <a>byte sequence</a> <var>a</var> is <dfn export>byte less than</dfn> a <a>byte sequence</a>
<var>b</var> if the following steps return true:
<ol>
<li><p>If <var>b</var> is a <a for="byte sequence">prefix</a> of <var>a</var>, then return false.
<li><p>If <var>a</var> is a <a for="byte sequence">prefix</a> of <var>b</var>, then return true.
<li><p>Let <var>n</var> be the smallest index such that the <var>n</var>th <a>byte</a> of
<var>a</var> is different from the <var>n</var>th byte of <var>b</var>. (There has to be such an
index, since neither byte sequence is a prefix of the other.)
<li><p>If the <var>n</var>th byte of <var>a</var> is less than the <var>n</var>th byte of
<var>b</var>, then return true.
<li><p>Return false.
</ol>
<hr>
<p>To <dfn export>isomorphic decode</dfn> a <a>byte sequence</a> <var>input</var>, return a
<a>string</a> whose <a for=string>code point length</a> is equal to <var>input</var>'s
<a for="byte sequence">length</a> and whose <a>code points</a> have the same
<a for="code point">values</a> as the <a for=byte>values</a> of <var>input</var>'s <a>bytes</a>, in
the same order.
<h3 id=code-points>Code points</h3>
<p>A <dfn export lt="code point|character">code point</dfn> is a Unicode code point and is
represented as "U+" followed by four-to-six <a>ASCII upper hex digits</a>, in the range U+0000 to
U+10FFFF, inclusive. A <a>code point</a>'s <dfn export for="code point">value</dfn> is its
underlying number.
<p>A <a>code point</a> may be followed by its name, by its rendered form between parentheses when it
is not U+0028 or U+0029, or by both. Documents using the Infra Standard are encouraged to follow
<a>code points</a> by their name when they cannot be rendered or are U+0028 or U+0029; otherwise,
follow them by their rendered form between parentheses, for legibility.
<p>A <a>code point</a>'s name is defined in <cite>Unicode</cite> and represented in
<a>ASCII uppercase</a>. [[!UNICODE]]
<div class=example id=example-code-point-notation>
<p>The <a>code point</a> rendered as 🤔 is represented as U+1F914.
<p>When referring to that <a>code point</a>, we might say "U+1F914 (🤔)", to provide extra context.
Documents are allowed to use "U+1F914 THINKING FACE (🤔)" as well, though this is somewhat verbose.
</div>
<p class=example id=example-code-point-notation-hard-to-render><a>Code points</a> that are difficult
to render unambigiously, such as U+000A, can be referred to as "U+000A LF". U+0029 can be referred
to as "U+0029 RIGHT PARENTHESIS", because even though it renders, this avoids unmatched parentheses.
<p><a>Code points</a> are sometimes referred to as <a>characters</a> and in certain contexts are
prefixed with "0x" rather than "U+".
<p>A <dfn export>leading surrogate</dfn> is a <a>code point</a> that is in the range U+D800 to
U+DBFF, inclusive.
<p>A <dfn export>trailing surrogate</dfn> is a <a>code point</a> that is in the range U+DC00 to
U+DFFF, inclusive.
<p>A <dfn export>surrogate</dfn> is a <a>leading surrogate</a> or a <a>trailing surrogate</a>.
<p>A <dfn export>scalar value</dfn> is a <a>code point</a> that is not a <a>surrogate</a>.
<p>A <dfn export>noncharacter</dfn> is a <a>code point</a> that is in the range U+FDD0 to U+FDEF,
inclusive, or U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF, U+3FFFE, U+3FFFF, U+4FFFE,
U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE, U+6FFFF, U+7FFFE, U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF,
U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF, U+DFFFE, U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE,
U+FFFFF, U+10FFFE, or U+10FFFF.
<p>An <dfn export>ASCII code point</dfn> is a <a>code point</a> in the range U+0000 NULL to
U+007F DELETE, inclusive.
<p>An <dfn export lt="ASCII tab or newline|ASCII tabs or newlines">ASCII tab or newline</dfn> is
U+0009 TAB, U+000A LF, or U+000D CR.
<p><dfn export>ASCII whitespace</dfn> is U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020
SPACE.
<p class=note>"Whitespace" is a mass noun.
<p>A <dfn export>C0 control</dfn> is a <a>code point</a> in the range U+0000 NULL to
U+001F INFORMATION SEPARATOR ONE, inclusive.
<p>A <dfn export lt="C0 control or space|C0 controls or spaces">C0 control or space</dfn> is a
<a>C0 control</a> or U+0020 SPACE.
<p>A <dfn export>control</dfn> is a <a>C0 control</a> or a <a>code point</a> in the range
U+007F DELETE to U+009F APPLICATION PROGRAM COMMAND, inclusive.
<p>An <dfn export>ASCII digit</dfn> is a <a>code point</a> in the range U+0030 (0) to U+0039 (9),
inclusive.
<p>An <dfn export>ASCII upper hex digit</dfn> is an <a>ASCII digit</a> or a <a>code point</a> in the
range U+0041 (A) to U+0046 (F), inclusive.
<p>An <dfn export>ASCII lower hex digit</dfn> is an <a>ASCII digit</a> or a <a>code point</a> in the
range U+0061 (a) to U+0066 (f), inclusive.
<p>An <dfn export>ASCII hex digit</dfn> is an <a>ASCII upper hex digit</a> or
<a>ASCII lower hex digit</a>.
<p>An <dfn export>ASCII upper alpha</dfn> is a <a>code point</a> in the range U+0041 (A) to
U+005A (Z), inclusive.
<p>An <dfn export>ASCII lower alpha</dfn> is a <a>code point</a> in the range U+0061 (a) to
U+007A (z), inclusive.
<p>An <dfn export>ASCII alpha</dfn> is an <a>ASCII upper alpha</a> or <a>ASCII lower alpha</a>.
<p>An <dfn export>ASCII alphanumeric</dfn> is an <a>ASCII digit</a> or <a>ASCII alpha</a>.
<h3 id=strings>Strings</h3>
<p>A <dfn export lt="string|JavaScript string">string</dfn> is a sequence of unsigned 16-bit
integers, also known as <dfn export lt="code unit">code units</dfn>. A <a>string</a> is also known
as a <a id="javascript-string">JavaScript string</a>. <a>Strings</a> are denoted by double quotes
and monospace font.
<p class=example id=example-string-notation>"<code>Hello, world!</code>" is a string.
<p class=note>This is different from how <cite>Unicode</cite> defines "code unit". In particular it
refers exclusively to how <cite>Unicode</cite> defines it for Unicode 16-bit strings. [[UNICODE]]
<p>A <a>string</a> can also be interpreted as containing <a>code points</a>, per the conversion
defined in <a>The String Type</a> section of the JavaScript specification. [[!ECMA-262]]
<p class=note>This conversion process converts surrogate pairs into their corresponding
<a>scalar value</a> and maps any remaining surrogates to their corresponding <a>code point</a>,
leaving them effectively as-is.
<p class=example id=example-javascript-string-in-code-points>A <a>string</a> consisting of the
<a>code units</a> 0xD83D, 0xDCA9, and 0xD800, when interpreted as containing <a>code points</a>,
would consist of the <a>code points</a> U+1F4A9 and U+D800.
<p>A <a>string</a>'s
<dfn export for="string,JavaScript string,scalar value string" id=string-length oldids=javascript-string-length>length</dfn>
is the number of <a>code units</a> it contains.
<p>A <a>string</a>'s
<dfn export for="string,JavaScript string,scalar value string">code point length</dfn> is the number
of <a>code points</a> it contains.
<p>A <dfn export>scalar value string</dfn> is a <a>string</a> whose <a>code points</a> are all
<a>scalar values</a>.
<p class=note>A <a>scalar value string</a> is useful for any kind of I/O or other kind of operation
where <a>UTF-8 encode</a> comes into play.
<!-- It's also useful if you can imagine the subsystem to be implemented in Rust -->
<p>To <dfn export for="string,JavaScript string" id=javascript-string-convert>convert</dfn> a
<a>string</a> into a <a>scalar value string</a>, replace any <a>surrogates</a> with U+FFFD (�).
<div class=note>
<p>The replaced surrogates are never part of surrogate pairs, since the process of interpreting the
string as containing <a>code points</a> will have converted surrogate pairs into
<a>scalar values</a>.
<p>A <a>scalar value string</a> can always be used as a <a>string</a> implicitly since every
<a>scalar value string</a> is a <a>string</a>. On the other hand, a <a>string</a> can only be
implicitly used as a <a>scalar value string</a> if it is known to not contain <a>surrogates</a>;
otherwise a <a for=string lt=convert>conversion</a> is to be performed.
<p>An implementation likely has to perform explicit conversion, depending on how it actually ends
up representing <a>strings</a> and <a>scalar value strings</a>. It is fairly typical for
implementations to have multiple implementations of <a>strings</a> alone for performance and memory
reasons.
</div>
<hr>
<p>A <a>string</a> <var>a</var> <dfn export for=string lt="is|identical to">is</dfn> or is
<a for=string>identical to</a> a <a>string</a> <var>b</var> if it consists of the same sequence of
<a>code units</a>.
<p>Except where otherwise stated, all string comparisons use <a for=string>is</a>.
<p class=note>This type of <a>string</a> comparison was formerly known as a "case-sensitive"
comparison in <cite>HTML</cite>. Strings that compare as <a for=string>identical to</a> one another
are not only sensitive to case variation (such as UPPER and lower case), but also to other code
point encoding choices, such as normalization form or the order of combining marks. Two strings that
are visually or even canonically equivalent according to <cite>Unicode</cite> might still not be
<a for=string>identical to</a> each other. [[HTML]] [[UNICODE]]
<p>A <a>string</a> <var>potentialPrefix</var> is a <dfn export>code unit prefix</dfn> of a
<a>string</a> <var>input</var> if the following steps return true:
<ol>
<li><p>Let <var>i</var> be 0.
<li>
<p><a>While</a> true:
<ol>
<li><p>If <var>i</var> is greater than or equal to <var>potentialPrefix</var>'s
<a for=string>length</a>, then return true.
<li><p>If <var>i</var> is greater than or equal to <var>input</var>'s <a for=string>length</a>,
then return false.
<li><p>Let <var>potentialPrefixCodeUnit</var> be the <var>i</var>th <a>code unit</a> of
<var>potentialPrefix</var>.
<li><p>Let <var>inputCodeUnit</var> be the <var>i</var>th <a>code unit</a> of <var>input</var>.
<li><p>Return false if <var>potentialPrefixCodeUnit</var> is not <var>inputCodeUnit</var>.
<li><p>Set <var>i</var> to <var>i</var> + 1.
</ol>
</li>
</ol>
<p>When it is clear from context that <a>code units</a> are in play, e.g., because one of the
strings is a literal containing only characters that are in the range U+0020 SPACE to U+007E (~),
"<var>input</var> <dfn export for="string">starts with</dfn> <var>potentialPrefix</var>" can be used
as a synonym for "<var>potentialPrefix</var> is a <a>code unit prefix</a> of <var>input</var>".
<p class=example id=code-unit-prefix-example>With unknown values, it is good to be explicit:
<var ignore>targetString</var> is a <a>code unit prefix</a> of <var>userInput</var>. But with a
literal, we can use plainer language: <var>userInput</var> <a for="string">starts with</a>
"<code>!</code>".
<p>A <a>string</a> <var>potentialSuffix</var> is a <dfn export>code unit suffix</dfn> of a
<a>string</a> <var>input</var> if the following steps return true:
<ol>
<li><p>Let <var>i</var> be 1.
<li>
<p><a>While</a> true:
<ol>
<li><p>Let <var>potentialSuffixIndex</var> be <var>potentialSuffix</var>'s
<a for=string>length</a> − <var>i</var>.
<li><p>Let <var>inputIndex</var> be <var>input</var>'s <a for=string>length</a> −
<var>i</var>.
<li><p>If <var>potentialSuffixIndex</var> is less than 0, then return true.
<li><p>If <var>inputIndex</var> is less than 0, then return false.
<li><p>Let <var>potentialSuffixCodeUnit</var> be the <var>potentialSuffixIndex</var>th
<a>code unit</a> of <var>potentialSuffix</var>.
<li><p>Let <var>inputCodeUnit</var> be the <var>inputIndex</var>th <a>code unit</a> of
<var>input</var>.