tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

value_subtyping.js (7760B)


      1 function simpleTypeSection(types) {
      2  return types.map((x, i) => `(type \$${i} ${x})`).join('\n');
      3 }
      4 
      5 function assertSubtype(superType, subType, types) {
      6  types = types || [];
      7  wasmEvalText(`(module
      8    ${types}
      9    (func
     10      unreachable
     11      (block (param ${subType})
     12        (block (param ${superType})
     13          drop
     14        )
     15      )
     16    )
     17  )`);
     18 }
     19 
     20 function assertNotSubtype(superType, subType, types) {
     21  assertErrorMessage(() => {
     22    assertSubtype(superType, subType, types);
     23  }, WebAssembly.CompileError, /type mismatch/);
     24 }
     25 
     26 // Primitive trivial subtyping
     27 assertSubtype('i32', 'i32');
     28 assertSubtype('i64', 'i64');
     29 assertSubtype('f32', 'f32');
     30 assertSubtype('f64', 'f64');
     31 assertSubtype('eqref', 'eqref');
     32 assertSubtype('i31ref', 'i31ref');
     33 assertSubtype('funcref', 'funcref');
     34 
     35 // No subtyping relation between funcref, anyref, externref. These are our top
     36 // types.
     37 assertNotSubtype('funcref', 'anyref');
     38 assertNotSubtype('anyref', 'funcref');
     39 assertNotSubtype('funcref', 'externref');
     40 assertNotSubtype('externref', 'funcref');
     41 assertNotSubtype('externref', 'anyref');
     42 assertNotSubtype('anyref', 'externref');
     43 
     44 // eqref is a subtype of anyref
     45 assertSubtype('anyref', 'eqref');
     46 
     47 // i31ref is a subtype of eqref
     48 assertSubtype('anyref', 'i31ref');
     49 assertSubtype('eqref', 'i31ref');
     50 
     51 // structref is a subtype of eqref and anyref
     52 assertSubtype('anyref', 'structref');
     53 assertSubtype('eqref', 'structref');
     54 
     55 // arrayref is a subtype of eqref and anyref
     56 assertSubtype('anyref', 'arrayref');
     57 assertSubtype('eqref', 'arrayref');
     58 
     59 // Structs are subtypes of anyref, eqref, and structref
     60 assertSubtype(
     61 'anyref',
     62 '(ref 0)',
     63 simpleTypeSection(['(struct)']));
     64 assertSubtype(
     65 'eqref',
     66 '(ref 0)',
     67 simpleTypeSection(['(struct)']));
     68 assertSubtype(
     69 'structref',
     70 '(ref 0)',
     71 simpleTypeSection(['(struct)']));
     72 
     73 // Struct identity
     74 assertSubtype(
     75 '(ref 0)',
     76 '(ref 1)',
     77 simpleTypeSection(['(struct)', '(struct)']));
     78 assertSubtype(
     79 '(ref 1)',
     80 '(ref 0)',
     81 simpleTypeSection(['(struct)', '(struct)']));
     82 
     83 // Self referential struct
     84 assertSubtype(
     85 '(ref 1)',
     86 '(ref 0)',
     87 simpleTypeSection(['(struct (field (ref 0)))', '(struct (field (ref 1)))']));
     88 
     89 // Mutually referential structs
     90 assertSubtype(
     91 '(ref 2)',
     92 '(ref 0)',
     93 `(rec
     94    (type (struct (field (ref 1))))
     95    (type (struct (field (ref 0))))
     96  )
     97  (rec
     98    (type (struct (field (ref 3))))
     99    (type (struct (field (ref 2))))
    100  )`);
    101 
    102 // Struct subtypes can have extra fields
    103 assertSubtype(
    104  '(ref 0)',
    105  '(ref 1)',
    106  `(type (sub (struct)))
    107   (type (sub 0 (struct (field i32))))`);
    108 assertSubtype(
    109  '(ref 0)',
    110  '(ref 1)',
    111  `(type (sub (struct)))
    112   (type (sub 0 (struct (field i32) (field i32))))`);
    113 
    114 // Struct supertypes cannot have extra fields
    115 assertNotSubtype(
    116  '(ref 0)',
    117  '(ref 1)',
    118  simpleTypeSection([
    119    '(struct (field i32))',
    120    '(struct)']));
    121 
    122 // Struct field mutability must match
    123 assertSubtype(
    124  '(ref 0)',
    125  '(ref 1)',
    126  simpleTypeSection([
    127    '(struct (field (mut i32)))',
    128    '(struct (field (mut i32)))']));
    129 assertSubtype(
    130  '(ref 0)',
    131  '(ref 1)',
    132  simpleTypeSection([
    133    '(struct (field i32))',
    134    '(struct (field i32))']));
    135 assertNotSubtype(
    136  '(ref 0)',
    137  '(ref 1)',
    138  simpleTypeSection([
    139    '(struct (field (mut i32)))',
    140    '(struct (field i32))']));
    141 assertNotSubtype(
    142  '(ref 0)',
    143  '(ref 1)',
    144  simpleTypeSection([
    145    '(struct (field i32))',
    146    '(struct (field (mut i32)))']));
    147 
    148 // Struct fields are invariant when mutable
    149 assertSubtype(
    150  '(ref 2)',
    151  '(ref 3)',
    152  simpleTypeSection([
    153    '(struct)',
    154    '(struct)',
    155    '(struct (field (mut (ref 0))))',
    156    '(struct (field (mut (ref 1))))']));
    157 assertNotSubtype(
    158  '(ref 2)',
    159  '(ref 3)',
    160  simpleTypeSection([
    161    '(struct)',
    162    '(struct (field i32))',
    163    '(struct (field (mut (ref 0))))',
    164    '(struct (field (mut (ref 1))))']));
    165 
    166 // Struct fields are covariant when immutable
    167 assertSubtype(
    168  '(ref 2)',
    169  '(ref 3)',
    170  `(type (sub (struct)))
    171   (type (sub 0 (struct (field i32))))
    172   (type (sub (struct (field (ref 0)))))
    173   (type (sub 2 (struct (field (ref 1)))))`);
    174 
    175 // Arrays are subtypes of anyref, eqref, and arrayref
    176 assertSubtype(
    177 'anyref',
    178 '(ref 0)',
    179 simpleTypeSection(['(array i32)']));
    180 assertSubtype(
    181 'eqref',
    182 '(ref 0)',
    183 simpleTypeSection(['(array i32)']));
    184 assertSubtype(
    185 'arrayref',
    186 '(ref 0)',
    187 simpleTypeSection(['(array i32)']));
    188 
    189 // Array identity
    190 assertSubtype(
    191 '(ref 0)',
    192 '(ref 1)',
    193 simpleTypeSection(['(array i32)', '(array i32)']));
    194 assertSubtype(
    195 '(ref 1)',
    196 '(ref 0)',
    197 simpleTypeSection(['(array i32)', '(array i32)']));
    198 
    199 // Self referential array
    200 assertSubtype(
    201 '(ref 1)',
    202 '(ref 0)',
    203 simpleTypeSection(['(array (ref 0))', '(array (ref 1))']));
    204 
    205 // Mutually referential arrays
    206 assertSubtype(
    207 '(ref 2)',
    208 '(ref 0)',
    209 `(rec
    210   (type (array (ref 1)))
    211   (type (array (ref 0)))
    212  )
    213  (rec
    214   (type (array (ref 3)))
    215   (type (array (ref 2)))
    216  )`);
    217 
    218 // Array mutability must match
    219 assertSubtype(
    220  '(ref 0)',
    221  '(ref 1)',
    222  simpleTypeSection([
    223    '(array (mut i32))',
    224    '(array (mut i32))']));
    225 assertSubtype(
    226  '(ref 0)',
    227  '(ref 1)',
    228  simpleTypeSection([
    229    '(array i32)',
    230    '(array i32)']));
    231 assertNotSubtype(
    232  '(ref 0)',
    233  '(ref 1)',
    234  simpleTypeSection([
    235    '(array (mut i32))',
    236    '(array i32)']));
    237 assertNotSubtype(
    238  '(ref 0)',
    239  '(ref 1)',
    240  simpleTypeSection([
    241    '(array i32)',
    242    '(array (mut i32))']));
    243 
    244 // Array elements are invariant when mutable
    245 assertSubtype(
    246  '(ref 2)',
    247  '(ref 3)',
    248  simpleTypeSection([
    249   '(struct)',
    250   '(struct)',
    251   '(array (mut (ref 0)))',
    252   '(array (mut (ref 1)))']));
    253 assertNotSubtype(
    254  '(ref 2)',
    255  '(ref 3)',
    256  simpleTypeSection([
    257   '(struct)',
    258   '(struct (field i32))',
    259   '(array (mut (ref 0)))',
    260   '(array (mut (ref 1)))']));
    261 
    262 // Array elements are covariant when immutable
    263 assertSubtype(
    264  '(ref 2)',
    265  '(ref 3)',
    266  simpleTypeSection([
    267  '(sub (struct))',
    268  '(sub 0 (struct (field i32)))',
    269  '(sub (array (ref 0)))',
    270  '(sub 2 (array (ref 1)))']));
    271 
    272 // nullref is a subtype of everything in anyref hierarchy
    273 assertSubtype('anyref', 'nullref');
    274 assertSubtype('eqref', 'nullref');
    275 assertSubtype('structref', 'nullref');
    276 assertSubtype('arrayref', 'nullref');
    277 assertSubtype('(ref null 0)', 'nullref', simpleTypeSection(['(struct)']));
    278 assertSubtype('(ref null 0)', 'nullref', simpleTypeSection(['(array i32)']));
    279 
    280 // nullref is not a subtype of any other hierarchy
    281 assertNotSubtype('funcref', 'nullref');
    282 assertNotSubtype('(ref null 0)', 'nullref', simpleTypeSection(['(func)']));
    283 assertNotSubtype('externref', 'nullref');
    284 
    285 // nullfuncref is a subtype of everything in funcref hierarchy
    286 assertSubtype('funcref', 'nullfuncref');
    287 assertSubtype('(ref null 0)', 'nullfuncref', simpleTypeSection(['(func)']));
    288 
    289 // nullfuncref is not a subtype of any other hierarchy
    290 assertNotSubtype('anyref', 'nullfuncref');
    291 assertNotSubtype('eqref', 'nullfuncref');
    292 assertNotSubtype('structref', 'nullfuncref');
    293 assertNotSubtype('arrayref', 'nullfuncref');
    294 assertNotSubtype('externref', 'nullfuncref');
    295 assertNotSubtype('(ref null 0)', 'nullfuncref', simpleTypeSection(['(struct)']));
    296 assertNotSubtype('(ref null 0)', 'nullfuncref', simpleTypeSection(['(array i32)']));
    297 
    298 // nullexternref is a subtype of everything in externref hierarchy
    299 assertSubtype('externref', 'nullexternref');
    300 
    301 // nullexternref is not a subtype of any other hierarchy
    302 assertNotSubtype('anyref', 'nullexternref');
    303 assertNotSubtype('eqref', 'nullexternref');
    304 assertNotSubtype('structref', 'nullexternref');
    305 assertNotSubtype('arrayref', 'nullexternref');
    306 assertNotSubtype('funcref', 'nullexternref');
    307 assertNotSubtype('(ref null 0)', 'nullexternref', simpleTypeSection(['(struct)']));
    308 assertNotSubtype('(ref null 0)', 'nullexternref', simpleTypeSection(['(array i32)']));
    309 assertNotSubtype('(ref null 0)', 'nullexternref', simpleTypeSection(['(func)']));