1;;! component_model_async = true 2 3;; bare bones "intrinsics work" 4(component 5 (type $r (resource (rep i32))) 6 (core func $rep (canon resource.rep $r)) 7 (core func $new (canon resource.new $r)) 8 (core func $drop (canon resource.drop $r)) 9 10 (core module $m 11 (import "" "rep" (func $rep (param i32) (result i32))) 12 (import "" "new" (func $new (param i32) (result i32))) 13 (import "" "drop" (func $drop (param i32))) 14 15 (func $start 16 (local $r i32) 17 (local.set $r (call $new (i32.const 100))) 18 19 (if (i32.ne (local.get $r) (i32.const 1)) (then (unreachable))) 20 (if (i32.ne (call $rep (local.get $r)) (i32.const 100)) (then (unreachable))) 21 22 (call $drop (local.get $r)) 23 ) 24 25 (start $start) 26 ) 27 (core instance (instantiate $m 28 (with "" (instance 29 (export "rep" (func $rep)) 30 (export "new" (func $new)) 31 (export "drop" (func $drop)) 32 )) 33 )) 34) 35 36;; cannot call `resource.drop` on a nonexistent resource 37(component 38 (type $r (resource (rep i32))) 39 (core func $drop (canon resource.drop $r)) 40 41 (core module $m 42 (import "" "drop" (func $drop (param i32))) 43 44 (func (export "r") 45 (call $drop (i32.const 0)) 46 ) 47 ) 48 (core instance $i (instantiate $m 49 (with "" (instance 50 (export "drop" (func $drop)) 51 )) 52 )) 53 54 (func (export "r") (canon lift (core func $i "r"))) 55) 56(assert_trap (invoke "r") "unknown handle index 0") 57 58;; cannot call `resource.rep` on a nonexistent resource 59(component 60 (type $r (resource (rep i32))) 61 (core func $rep (canon resource.rep $r)) 62 63 (core module $m 64 (import "" "rep" (func $rep (param i32) (result i32))) 65 66 (func (export "r") 67 (drop (call $rep (i32.const 0))) 68 ) 69 ) 70 (core instance $i (instantiate $m 71 (with "" (instance 72 (export "rep" (func $rep)) 73 )) 74 )) 75 76 (func (export "r") (canon lift (core func $i "r"))) 77) 78(assert_trap (invoke "r") "unknown handle index 0") 79 80;; index reuse behavior of handles 81(component 82 (type $r (resource (rep i32))) 83 (core func $rep (canon resource.rep $r)) 84 (core func $new (canon resource.new $r)) 85 (core func $drop (canon resource.drop $r)) 86 87 (core module $m 88 (import "" "rep" (func $rep (param i32) (result i32))) 89 (import "" "new" (func $new (param i32) (result i32))) 90 (import "" "drop" (func $drop (param i32))) 91 92 (func $start 93 (local $r1 i32) 94 (local $r2 i32) 95 (local $r3 i32) 96 (local $r4 i32) 97 98 ;; resources assigned sequentially 99 (local.set $r1 (call $new (i32.const 100))) 100 (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) 101 102 (local.set $r2 (call $new (i32.const 200))) 103 (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) 104 105 (local.set $r3 (call $new (i32.const 300))) 106 (if (i32.ne (local.get $r3) (i32.const 3)) (then (unreachable))) 107 108 ;; representations all look good 109 (if (i32.ne (call $rep (local.get $r1)) (i32.const 100)) (then (unreachable))) 110 (if (i32.ne (call $rep (local.get $r2)) (i32.const 200)) (then (unreachable))) 111 (if (i32.ne (call $rep (local.get $r3)) (i32.const 300)) (then (unreachable))) 112 113 ;; reallocate r2 114 (call $drop (local.get $r2)) 115 (local.set $r2 (call $new (i32.const 400))) 116 117 ;; should have reused index 3 118 (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) 119 120 ;; representations all look good 121 (if (i32.ne (call $rep (local.get $r1)) (i32.const 100)) (then (unreachable))) 122 (if (i32.ne (call $rep (local.get $r2)) (i32.const 400)) (then (unreachable))) 123 (if (i32.ne (call $rep (local.get $r3)) (i32.const 300)) (then (unreachable))) 124 125 ;; deallocate, then reallocate 126 (call $drop (local.get $r1)) 127 (call $drop (local.get $r2)) 128 (call $drop (local.get $r3)) 129 130 (local.set $r1 (call $new (i32.const 500))) 131 (local.set $r2 (call $new (i32.const 600))) 132 (local.set $r3 (call $new (i32.const 700))) 133 134 ;; representations all look good 135 (if (i32.ne (call $rep (local.get $r1)) (i32.const 500)) (then (unreachable))) 136 (if (i32.ne (call $rep (local.get $r2)) (i32.const 600)) (then (unreachable))) 137 (if (i32.ne (call $rep (local.get $r3)) (i32.const 700)) (then (unreachable))) 138 139 ;; indices should be lifo 140 (if (i32.ne (local.get $r1) (i32.const 3)) (then (unreachable))) 141 (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) 142 (if (i32.ne (local.get $r3) (i32.const 1)) (then (unreachable))) 143 144 ;; bump one more time 145 (local.set $r4 (call $new (i32.const 800))) 146 (if (i32.ne (local.get $r4) (i32.const 4)) (then (unreachable))) 147 148 ;; deallocate everything 149 (call $drop (local.get $r1)) 150 (call $drop (local.get $r2)) 151 (call $drop (local.get $r3)) 152 (call $drop (local.get $r4)) 153 ) 154 155 (start $start) 156 ) 157 (core instance (instantiate $m 158 (with "" (instance 159 (export "rep" (func $rep)) 160 (export "new" (func $new)) 161 (export "drop" (func $drop)) 162 )) 163 )) 164) 165 166(assert_unlinkable 167 (component 168 (import "host" (instance 169 (export "missing" (type (sub resource))) 170 )) 171 ) 172 "was not found") 173(assert_unlinkable 174 (component 175 (import "host" (instance 176 (export "return-three" (type (sub resource))) 177 )) 178 ) 179 "expected resource found func") 180 181;; all resources can be uniquely imported 182(component 183 (import "host" (instance 184 (export "resource1" (type (sub resource))) 185 (export "resource2" (type (sub resource))) 186 (export "resource1-again" (type (sub resource))) 187 )) 188) 189 190;; equality constraints also work 191(component 192 (import "host" (instance 193 (export "resource1" (type $r1 (sub resource))) 194 (export "resource2" (type (sub resource))) 195 (export "resource1-again" (type (eq $r1))) 196 )) 197) 198 199;; equality constraints are checked if resources are supplied 200(assert_unlinkable 201 (component 202 (import "host" (instance 203 (export "resource1" (type (sub resource))) 204 (export "resource2" (type $r1 (sub resource))) 205 (export "resource1-again" (type (eq $r1))) 206 )) 207 ) 208 "mismatched resource types") 209 210;; equality constraints mean that types don't need to be supplied 211(component 212 (import "host" (instance 213 (export "resource1" (type $r1 (sub resource))) 214 (export "resource2" (type (sub resource))) 215 (export "this-name-is-not-provided-in-the-wast-harness" (type (eq $r1))) 216 )) 217) 218 219;; simple properties of handles 220(component 221 (import "host" (instance $host 222 (export "resource1" (type $r (sub resource))) 223 (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) 224 (export "[static]resource1.assert" (func (param "r" (own $r)) (param "rep" u32))) 225 )) 226 (alias export $host "resource1" (type $r)) 227 (alias export $host "[constructor]resource1" (func $ctor)) 228 (alias export $host "[static]resource1.assert" (func $assert)) 229 230 (core func $drop (canon resource.drop $r)) 231 (core func $ctor (canon lower (func $ctor))) 232 (core func $assert (canon lower (func $assert))) 233 234 (core module $m 235 (import "" "drop" (func $drop (param i32))) 236 (import "" "ctor" (func $ctor (param i32) (result i32))) 237 (import "" "assert" (func $assert (param i32 i32))) 238 239 (func $start 240 (local $r1 i32) 241 (local $r2 i32) 242 (local.set $r1 (call $ctor (i32.const 100))) 243 (local.set $r2 (call $ctor (i32.const 200))) 244 245 ;; assert r1/r2 are sequential 246 (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) 247 (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) 248 249 ;; reallocate r1 and it should be reassigned the same index 250 (call $drop (local.get $r1)) 251 (local.set $r1 (call $ctor (i32.const 300))) 252 (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) 253 254 ;; internal values should match 255 (call $assert (local.get $r1) (i32.const 300)) 256 (call $assert (local.get $r2) (i32.const 200)) 257 ) 258 259 (start $start) 260 ) 261 (core instance (instantiate $m 262 (with "" (instance 263 (export "drop" (func $drop)) 264 (export "ctor" (func $ctor)) 265 (export "assert" (func $assert)) 266 )) 267 )) 268) 269 270;; Using an index that has never been valid is a trap 271(component 272 (import "host" (instance $host 273 (export "resource1" (type $r (sub resource))) 274 (export "[static]resource1.assert" (func (param "r" (own $r)) (param "rep" u32))) 275 )) 276 (alias export $host "resource1" (type $r)) 277 (alias export $host "[static]resource1.assert" (func $assert)) 278 (core func $assert (canon lower (func $assert))) 279 280 (core module $m 281 (import "" "assert" (func $assert (param i32 i32))) 282 283 (func (export "f") 284 (call $assert (i32.const 0) (i32.const 0)) 285 ) 286 ) 287 (core instance $i (instantiate $m 288 (with "" (instance 289 (export "assert" (func $assert)) 290 )) 291 )) 292 293 (func (export "f") (canon lift (core func $i "f"))) 294) 295 296(assert_trap (invoke "f") "unknown handle index") 297 298;; Using an index which was previously valid but no longer valid is also a trap. 299(component 300 (import "host" (instance $host 301 (export "resource1" (type $r (sub resource))) 302 (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) 303 (export "[static]resource1.assert" (func (param "r" (own $r)) (param "rep" u32))) 304 )) 305 (alias export $host "[constructor]resource1" (func $ctor)) 306 (alias export $host "[static]resource1.assert" (func $assert)) 307 308 (core func $assert (canon lower (func $assert))) 309 (core func $ctor (canon lower (func $ctor))) 310 311 (core module $m 312 (import "" "assert" (func $assert (param i32 i32))) 313 (import "" "ctor" (func $ctor (param i32) (result i32))) 314 315 (global $handle (mut i32) i32.const 0) 316 317 (func (export "f") 318 (global.set $handle (call $ctor (i32.const 100))) 319 (call $assert (global.get $handle) (i32.const 100)) 320 ) 321 322 (func (export "f2") 323 (call $assert (global.get $handle) (i32.const 100)) 324 ) 325 ) 326 (core instance $i (instantiate $m 327 (with "" (instance 328 (export "assert" (func $assert)) 329 (export "ctor" (func $ctor)) 330 )) 331 )) 332 333 (func (export "f") (canon lift (core func $i "f"))) 334 (func (export "f2") (canon lift (core func $i "f2"))) 335) 336 337(assert_return (invoke "f")) 338(assert_trap (invoke "f2") "unknown handle index") 339 340;; Also invalid to pass a previously valid handle to the drop intrinsic 341(component 342 (import "host" (instance $host 343 (export "resource1" (type $r (sub resource))) 344 (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) 345 )) 346 (alias export $host "resource1" (type $r)) 347 (alias export $host "[constructor]resource1" (func $ctor)) 348 349 (core func $drop (canon resource.drop $r)) 350 (core func $ctor (canon lower (func $ctor))) 351 352 (core module $m 353 (import "" "drop" (func $drop (param i32))) 354 (import "" "ctor" (func $ctor (param i32) (result i32))) 355 356 (global $handle (mut i32) i32.const 0) 357 358 (func (export "f") 359 (global.set $handle (call $ctor (i32.const 100))) 360 (call $drop (global.get $handle)) 361 ) 362 363 (func (export "f2") 364 (call $drop (global.get $handle)) 365 ) 366 ) 367 (core instance $i (instantiate $m 368 (with "" (instance 369 (export "ctor" (func $ctor)) 370 (export "drop" (func $drop)) 371 )) 372 )) 373 374 (func (export "f") (canon lift (core func $i "f"))) 375 (func (export "f2") (canon lift (core func $i "f2"))) 376) 377 378(assert_return (invoke "f")) 379(assert_trap (invoke "f2") "unknown handle index") 380 381;; If an inner component instantiates a resource then an outer component 382;; should not implicitly have access to that resource. 383(component 384 (import "host" (instance $host 385 (export "resource1" (type $r (sub resource))) 386 (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) 387 )) 388 389 ;; an inner component which upon instantiation will invoke the constructor, 390 ;; assert that it's zero, and then forget about it. 391 (component $inner 392 (import "host" (instance $host 393 (export "resource1" (type $r (sub resource))) 394 (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) 395 )) 396 (alias export $host "[constructor]resource1" (func $ctor)) 397 398 (core func $ctor (canon lower (func $ctor))) 399 400 (core module $m 401 (import "" "ctor" (func $ctor (param i32) (result i32))) 402 403 (func $start 404 (if (i32.ne (call $ctor (i32.const 100)) (i32.const 0)) (then (unreachable))) 405 ) 406 ) 407 (core instance $i (instantiate $m 408 (with "" (instance (export "ctor" (func $ctor)))) 409 )) 410 ) 411 (instance $i (instantiate $inner (with "host" (instance $host)))) 412 413 ;; the rest of this component which is a single function that invokes `drop` 414 ;; for index 0. The index 0 should be valid within the above component, but 415 ;; it is not valid within this component 416 (alias export $host "resource1" (type $r)) 417 (core func $drop (canon resource.drop $r)) 418 419 (core module $m 420 (import "" "drop" (func $drop (param i32))) 421 422 (func (export "f") 423 (call $drop (i32.const 0)) 424 ) 425 ) 426 (core instance $i (instantiate $m 427 (with "" (instance 428 (export "drop" (func $drop)) 429 )) 430 )) 431 432 (func (export "f") (canon lift (core func $i "f"))) 433) 434 435(assert_trap (invoke "f") "unknown handle index") 436 437;; Same as the above test, but for resources defined within a component 438(component 439 (component $inner 440 (type $r (resource (rep i32))) 441 442 (core func $ctor (canon resource.new $r)) 443 444 (core module $m 445 (import "" "ctor" (func $ctor (param i32) (result i32))) 446 447 (func $start 448 (if (i32.ne (call $ctor (i32.const 100)) (i32.const 1)) (then (unreachable))) 449 ) 450 (start $start) 451 ) 452 (core instance $i (instantiate $m 453 (with "" (instance (export "ctor" (func $ctor)))) 454 )) 455 (export "r" (type $r)) 456 ) 457 (instance $i (instantiate $inner)) 458 459 ;; the rest of this component which is a single function that invokes `drop` 460 ;; for index 2. The index 2 should be valid within the above component, but 461 ;; it is not valid within this component 462 (alias export $i "r" (type $r)) 463 (core func $drop (canon resource.drop $r)) 464 465 (core module $m 466 (import "" "drop" (func $drop (param i32))) 467 468 (func (export "f") 469 (call $drop (i32.const 2)) 470 ) 471 ) 472 (core instance $i (instantiate $m 473 (with "" (instance 474 (export "drop" (func $drop)) 475 )) 476 )) 477 478 (func (export "f") (canon lift (core func $i "f"))) 479) 480 481(assert_trap (invoke "f") "unknown handle index 2") 482 483;; Each instantiation of a component generates a unique resource type, so 484;; allocating in one component and deallocating in another should fail. 485(component 486 (component $inner 487 (type $r (resource (rep i32))) 488 489 (core func $ctor (canon resource.new $r)) 490 (core func $drop (canon resource.drop $r)) 491 492 (core module $m 493 (import "" "ctor" (func $ctor (param i32) (result i32))) 494 (import "" "drop" (func $drop (param i32))) 495 496 (func (export "alloc") 497 (if (i32.ne (call $ctor (i32.const 100)) (i32.const 1)) (then (unreachable))) 498 ) 499 (func (export "dealloc") 500 (call $drop (i32.const 1)) 501 ) 502 ) 503 (core instance $i (instantiate $m 504 (with "" (instance 505 (export "ctor" (func $ctor)) 506 (export "drop" (func $drop)) 507 )) 508 )) 509 (func (export "alloc") (canon lift (core func $i "alloc"))) 510 (func (export "dealloc") (canon lift (core func $i "dealloc"))) 511 ) 512 (instance $i1 (instantiate $inner)) 513 (instance $i2 (instantiate $inner)) 514 515 (alias export $i1 "alloc" (func $alloc_in_1)) 516 (alias export $i1 "dealloc" (func $dealloc_in_1)) 517 (alias export $i2 "alloc" (func $alloc_in_2)) 518 (alias export $i2 "dealloc" (func $dealloc_in_2)) 519 520 (export "alloc-in1" (func $alloc_in_1)) 521 (export "dealloc-in1" (func $dealloc_in_1)) 522 (export "alloc-in2" (func $alloc_in_2)) 523 (export "dealloc-in2" (func $dealloc_in_2)) 524) 525 526(assert_return (invoke "alloc-in1")) 527(assert_return (invoke "dealloc-in1")) 528(assert_return (invoke "alloc-in1")) 529(assert_return (invoke "alloc-in2")) 530(assert_return (invoke "dealloc-in2")) 531(assert_trap (invoke "dealloc-in2") "unknown handle index") 532 533;; Same as above, but the same host resource type is imported into a 534;; component that is instantiated twice. Each component instance should 535;; receive different tables tracking resources so a resource allocated in one 536;; should not be visible in the other. 537(component 538 (import "host" (instance $host 539 (export "resource1" (type $r (sub resource))) 540 (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) 541 )) 542 (alias export $host "resource1" (type $r)) 543 (alias export $host "[constructor]resource1" (func $ctor)) 544 545 (component $inner 546 (import "r" (type $r (sub resource))) 547 (import "[constructor]r" (func $ctor (param "r" u32) (result (own $r)))) 548 549 (core func $ctor (canon lower (func $ctor))) 550 (core func $drop (canon resource.drop $r)) 551 552 (core module $m 553 (import "" "ctor" (func $ctor (param i32) (result i32))) 554 (import "" "drop" (func $drop (param i32))) 555 556 (func (export "alloc") 557 (if (i32.ne (call $ctor (i32.const 100)) (i32.const 1)) (then (unreachable))) 558 ) 559 (func (export "dealloc") 560 (call $drop (i32.const 1)) 561 ) 562 ) 563 (core instance $i (instantiate $m 564 (with "" (instance 565 (export "ctor" (func $ctor)) 566 (export "drop" (func $drop)) 567 )) 568 )) 569 (func (export "alloc") (canon lift (core func $i "alloc"))) 570 (func (export "dealloc") (canon lift (core func $i "dealloc"))) 571 ) 572 (instance $i1 (instantiate $inner 573 (with "r" (type $r)) 574 (with "[constructor]r" (func $ctor)) 575 )) 576 (instance $i2 (instantiate $inner 577 (with "r" (type $r)) 578 (with "[constructor]r" (func $ctor)) 579 )) 580 581 (alias export $i1 "alloc" (func $alloc_in_1)) 582 (alias export $i1 "dealloc" (func $dealloc_in_1)) 583 (alias export $i2 "alloc" (func $alloc_in_2)) 584 (alias export $i2 "dealloc" (func $dealloc_in_2)) 585 586 (export "alloc-in1" (func $alloc_in_1)) 587 (export "dealloc-in1" (func $dealloc_in_1)) 588 (export "alloc-in2" (func $alloc_in_2)) 589 (export "dealloc-in2" (func $dealloc_in_2)) 590) 591 592(assert_return (invoke "alloc-in1")) 593(assert_return (invoke "dealloc-in1")) 594(assert_return (invoke "alloc-in1")) 595(assert_return (invoke "alloc-in2")) 596(assert_return (invoke "dealloc-in2")) 597(assert_trap (invoke "dealloc-in2") "unknown handle index") 598 599;; Multiple copies of intrinsics all work 600(component 601 (type $r (resource (rep i32))) 602 603 (core func $new1 (canon resource.new $r)) 604 (core func $new2 (canon resource.new $r)) 605 (core func $drop1 (canon resource.drop $r)) 606 (core func $drop2 (canon resource.drop $r)) 607 608 (core module $m 609 (import "" "new1" (func $new1 (param i32) (result i32))) 610 (import "" "new2" (func $new2 (param i32) (result i32))) 611 (import "" "drop1" (func $drop1 (param i32))) 612 (import "" "drop2" (func $drop2 (param i32))) 613 614 (func $start 615 ;; 2x2 matrix of pairing new/drop 616 (call $drop1 (call $new1 (i32.const 101))) 617 (call $drop2 (call $new1 (i32.const 102))) 618 (call $drop1 (call $new2 (i32.const 103))) 619 (call $drop2 (call $new2 (i32.const 104))) 620 621 ;; should be referencing the same namespace 622 (if (i32.ne (call $new1 (i32.const 105)) (i32.const 1)) (then (unreachable))) 623 (if (i32.ne (call $new2 (i32.const 105)) (i32.const 2)) (then (unreachable))) 624 625 ;; use different drops out of order 626 (call $drop2 (i32.const 1)) 627 (call $drop1 (i32.const 2)) 628 ) 629 630 (start $start) 631 ) 632 633 (core instance (instantiate $m 634 (with "" (instance 635 (export "new1" (func $new1)) 636 (export "new2" (func $new2)) 637 (export "drop1" (func $drop1)) 638 (export "drop2" (func $drop2)) 639 )) 640 )) 641) 642 643;; u32::MAX isn't special in some weird way, it's just probably always invalid 644;; because that's a lot of handles. 645(component 646 (type $r (resource (rep i32))) 647 648 (core func $drop (canon resource.drop $r)) 649 650 (core module $m 651 (import "" "drop" (func $drop (param i32))) 652 653 (func (export "f") 654 (call $drop (i32.const 0xffffffff)) 655 ) 656 ) 657 658 (core instance $i (instantiate $m 659 (with "" (instance 660 (export "drop" (func $drop)) 661 )) 662 )) 663 (func (export "f") (canon lift (core func $i "f"))) 664) 665(assert_trap (invoke "f") "unknown handle index") 666 667;; Test behavior of running a destructor for local resources 668(component 669 (core module $m1 670 (global $drops (mut i32) i32.const 0) 671 (global $last_drop (mut i32) i32.const -1) 672 673 (func (export "dtor") (param i32) 674 (global.set $drops (i32.add (global.get $drops) (i32.const 1))) 675 (global.set $last_drop (local.get 0)) 676 ) 677 (func (export "drops") (result i32) global.get $drops) 678 (func (export "last-drop") (result i32) global.get $last_drop) 679 ) 680 (core instance $i1 (instantiate $m1)) 681 682 (type $r1 (resource (rep i32))) 683 (type $r2 (resource (rep i32) (dtor (func $i1 "dtor")))) 684 685 (core func $drop1 (canon resource.drop $r1)) 686 (core func $drop2 (canon resource.drop $r2)) 687 (core func $new1 (canon resource.new $r1)) 688 (core func $new2 (canon resource.new $r2)) 689 690 (core module $m2 691 (import "" "drop1" (func $drop1 (param i32))) 692 (import "" "drop2" (func $drop2 (param i32))) 693 (import "" "new1" (func $new1 (param i32) (result i32))) 694 (import "" "new2" (func $new2 (param i32) (result i32))) 695 (import "i1" "drops" (func $drops (result i32))) 696 (import "i1" "last-drop" (func $last-drop (result i32))) 697 698 (func $start 699 (local $r1 i32) 700 (local $r2 i32) 701 702 (local.set $r1 (call $new1 (i32.const 100))) 703 (local.set $r2 (call $new2 (i32.const 200))) 704 705 ;; indexes start at 1 and while they have distinct types they should be 706 ;; within the same table. 707 (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) 708 (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) 709 710 ;; nothing should be dropped yet 711 (if (i32.ne (call $drops) (i32.const 0)) (then (unreachable))) 712 (if (i32.ne (call $last-drop) (i32.const -1)) (then (unreachable))) 713 714 ;; dropping a resource without a destructor is ok, but shouldn't tamper 715 ;; with anything. 716 (call $drop1 (local.get $r1)) 717 (if (i32.ne (call $drops) (i32.const 0)) (then (unreachable))) 718 (if (i32.ne (call $last-drop) (i32.const -1)) (then (unreachable))) 719 720 ;; drop r2 which should record a drop and additionally record the private 721 ;; representation value which was dropped 722 (call $drop2 (local.get $r2)) 723 (if (i32.ne (call $drops) (i32.const 1)) (then (unreachable))) 724 (if (i32.ne (call $last-drop) (i32.const 200)) (then (unreachable))) 725 726 ;; do it all over again 727 (local.set $r2 (call $new2 (i32.const 300))) 728 (call $drop2 (local.get $r2)) 729 (if (i32.ne (call $drops) (i32.const 2)) (then (unreachable))) 730 (if (i32.ne (call $last-drop) (i32.const 300)) (then (unreachable))) 731 ) 732 733 (start $start) 734 ) 735 736 (core instance $i2 (instantiate $m2 737 (with "" (instance 738 (export "drop1" (func $drop1)) 739 (export "drop2" (func $drop2)) 740 (export "new1" (func $new1)) 741 (export "new2" (func $new2)) 742 )) 743 (with "i1" (instance $i1)) 744 )) 745) 746 747;; Test dropping a host resource 748(component 749 (import "host" (instance $host 750 (export "resource1" (type $r (sub resource))) 751 (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) 752 (export "[static]resource1.last-drop" (func (result u32))) 753 (export "[static]resource1.drops" (func (result u32))) 754 )) 755 756 (alias export $host "resource1" (type $r)) 757 (alias export $host "[constructor]resource1" (func $ctor)) 758 (alias export $host "[static]resource1.last-drop" (func $last-drop)) 759 (alias export $host "[static]resource1.drops" (func $drops)) 760 761 (core func $drop (canon resource.drop $r)) 762 (core func $ctor (canon lower (func $ctor))) 763 (core func $last-drop (canon lower (func $last-drop))) 764 (core func $drops (canon lower (func $drops))) 765 766 (core module $m 767 (import "" "drop" (func $drop (param i32))) 768 (import "" "ctor" (func $ctor (param i32) (result i32))) 769 (import "" "last-drop" (func $last-drop (result i32))) 770 (import "" "drops" (func $raw-drops (result i32))) 771 772 (global $init-drop-cnt (mut i32) i32.const 0) 773 774 (func $drops (result i32) 775 (i32.sub (call $raw-drops) (global.get $init-drop-cnt)) 776 ) 777 778 (func $start 779 (local $r1 i32) 780 (global.set $init-drop-cnt (call $raw-drops)) 781 782 (local.set $r1 (call $ctor (i32.const 100))) 783 784 ;; should be no drops yet 785 (if (i32.ne (call $drops) (i32.const 0)) (then (unreachable))) 786 787 ;; should count a drop 788 (call $drop (local.get $r1)) 789 (if (i32.ne (call $drops) (i32.const 1)) (then (unreachable))) 790 (if (i32.ne (call $last-drop) (i32.const 100)) (then (unreachable))) 791 792 ;; do it again to be sure 793 (local.set $r1 (call $ctor (i32.const 200))) 794 (call $drop (local.get $r1)) 795 (if (i32.ne (call $drops) (i32.const 2)) (then (unreachable))) 796 (if (i32.ne (call $last-drop) (i32.const 200)) (then (unreachable))) 797 ) 798 799 (start $start) 800 ) 801 (core instance (instantiate $m 802 (with "" (instance 803 (export "drop" (func $drop)) 804 (export "ctor" (func $ctor)) 805 (export "last-drop" (func $last-drop)) 806 (export "drops" (func $drops)) 807 )) 808 )) 809) 810 811;; Test some bare-bones basics of borrowed resources 812(component 813 (import "host" (instance $host 814 (export "resource1" (type $r (sub resource))) 815 (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) 816 (export "[method]resource1.simple" (func (param "self" (borrow $r)) (param "rep" u32))) 817 (export "[method]resource1.take-borrow" (func (param "self" (borrow $r)) (param "b" (borrow $r)))) 818 (export "[method]resource1.take-own" (func (param "self" (borrow $r)) (param "b" (own $r)))) 819 )) 820 821 (alias export $host "resource1" (type $r)) 822 (alias export $host "[constructor]resource1" (func $ctor)) 823 (alias export $host "[method]resource1.simple" (func $simple)) 824 (alias export $host "[method]resource1.take-borrow" (func $take-borrow)) 825 (alias export $host "[method]resource1.take-own" (func $take-own)) 826 827 (core func $drop (canon resource.drop $r)) 828 (core func $ctor (canon lower (func $ctor))) 829 (core func $simple (canon lower (func $simple))) 830 (core func $take-own (canon lower (func $take-own))) 831 (core func $take-borrow (canon lower (func $take-borrow))) 832 833 (core module $m 834 (import "" "drop" (func $drop (param i32))) 835 (import "" "ctor" (func $ctor (param i32) (result i32))) 836 (import "" "simple" (func $simple (param i32 i32))) 837 (import "" "take-own" (func $take-own (param i32 i32))) 838 (import "" "take-borrow" (func $take-borrow (param i32 i32))) 839 840 841 (func $start 842 (local $r1 i32) 843 (local $r2 i32) 844 (local.set $r1 (call $ctor (i32.const 100))) 845 (local.set $r2 (call $ctor (i32.const 200))) 846 847 (call $simple (local.get $r1) (i32.const 100)) 848 (call $simple (local.get $r1) (i32.const 100)) 849 (call $simple (local.get $r2) (i32.const 200)) 850 (call $simple (local.get $r1) (i32.const 100)) 851 (call $simple (local.get $r2) (i32.const 200)) 852 (call $simple (local.get $r2) (i32.const 200)) 853 854 (call $drop (local.get $r1)) 855 (call $drop (local.get $r2)) 856 857 858 (local.set $r1 (call $ctor (i32.const 200))) 859 (local.set $r2 (call $ctor (i32.const 300))) 860 (call $take-borrow (local.get $r1) (local.get $r2)) 861 (call $take-borrow (local.get $r2) (local.get $r1)) 862 (call $take-borrow (local.get $r1) (local.get $r1)) 863 (call $take-borrow (local.get $r2) (local.get $r2)) 864 865 (call $take-own (local.get $r1) (call $ctor (i32.const 400))) 866 (call $take-own (local.get $r2) (call $ctor (i32.const 500))) 867 (call $take-own (local.get $r2) (local.get $r1)) 868 (call $drop (local.get $r2)) 869 870 ;; table should be empty at this point, so a fresh allocation should get 871 ;; index 2 872 (if (i32.ne (call $ctor (i32.const 600)) (i32.const 1)) (then (unreachable))) 873 ) 874 875 (start $start) 876 ) 877 (core instance (instantiate $m 878 (with "" (instance 879 (export "drop" (func $drop)) 880 (export "ctor" (func $ctor)) 881 (export "simple" (func $simple)) 882 (export "take-own" (func $take-own)) 883 (export "take-borrow" (func $take-borrow)) 884 )) 885 )) 886) 887 888;; Cannot pass out an owned resource when it's borrowed by the same call 889(component 890 (import "host" (instance $host 891 (export "resource1" (type $r (sub resource))) 892 (export "[constructor]resource1" (func (param "r" u32) (result (own $r)))) 893 (export "[method]resource1.take-own" (func (param "self" (borrow $r)) (param "b" (own $r)))) 894 )) 895 896 (alias export $host "resource1" (type $r)) 897 (alias export $host "[constructor]resource1" (func $ctor)) 898 (alias export $host "[method]resource1.take-own" (func $take-own)) 899 900 (core func $drop (canon resource.drop $r)) 901 (core func $ctor (canon lower (func $ctor))) 902 (core func $take-own (canon lower (func $take-own))) 903 904 (core module $m 905 (import "" "drop" (func $drop (param i32))) 906 (import "" "ctor" (func $ctor (param i32) (result i32))) 907 (import "" "take-own" (func $take-own (param i32 i32))) 908 909 910 (func (export "f") 911 (local $r i32) 912 (local.set $r (call $ctor (i32.const 100))) 913 (call $take-own (local.get $r) (local.get $r)) 914 ) 915 ) 916 (core instance $i (instantiate $m 917 (with "" (instance 918 (export "drop" (func $drop)) 919 (export "ctor" (func $ctor)) 920 (export "take-own" (func $take-own)) 921 )) 922 )) 923 924 (func (export "f") (canon lift (core func $i "f"))) 925) 926 927(assert_trap (invoke "f") "cannot remove owned resource while borrowed") 928 929;; Borrows must actually exist 930(component 931 (import "host" (instance $host 932 (export "resource1" (type $r (sub resource))) 933 (export "[method]resource1.simple" (func (param "self" (borrow $r)) (param "b" u32))) 934 )) 935 936 (alias export $host "resource1" (type $r)) 937 (alias export $host "[method]resource1.simple" (func $simple)) 938 939 (core func $drop (canon resource.drop $r)) 940 (core func $simple (canon lower (func $simple))) 941 942 (core module $m 943 (import "" "drop" (func $drop (param i32))) 944 (import "" "simple" (func $simple (param i32 i32))) 945 946 947 (func (export "f") 948 (call $simple (i32.const 0) (i32.const 0)) 949 ) 950 ) 951 (core instance $i (instantiate $m 952 (with "" (instance 953 (export "drop" (func $drop)) 954 (export "simple" (func $simple)) 955 )) 956 )) 957 958 (func (export "f") (canon lift (core func $i "f"))) 959) 960 961(assert_trap (invoke "f") "unknown handle index 0") 962 963(component 964 (component $A 965 (type $t' (resource (rep i32))) 966 (export $t "t" (type $t')) 967 968 (core func $ctor (canon resource.new $t)) 969 (core func $dtor (canon resource.drop $t)) 970 (core func $rep (canon resource.rep $t)) 971 972 (core module $m 973 (import "" "dtor" (func $dtor (param i32))) 974 (import "" "rep" (func $rep (param i32) (result i32))) 975 976 (func (export "[method]t.assert") (param i32 i32) 977 (if (i32.ne (local.get 0) (local.get 1)) (then (unreachable))) 978 ) 979 (func (export "[static]t.assert-own") (param i32 i32) 980 (if (i32.ne (call $rep (local.get 0)) (local.get 1)) (then (unreachable))) 981 (call $dtor (local.get 0)) 982 ) 983 ) 984 (core instance $i (instantiate $m 985 (with "" (instance 986 (export "dtor" (func $dtor)) 987 (export "rep" (func $rep)) 988 )) 989 )) 990 (func (export "[constructor]t") (param "x" u32) (result (own $t)) 991 (canon lift (core func $ctor))) 992 (func (export "[method]t.assert") (param "self" (borrow $t)) (param "x" u32) 993 (canon lift (core func $i "[method]t.assert"))) 994 (func (export "[static]t.assert-own") (param "self" (own $t)) (param "x" u32) 995 (canon lift (core func $i "[static]t.assert-own"))) 996 ) 997 (instance $a (instantiate $A)) 998 999 (component $B 1000 (import "a" (instance $i 1001 (export "t" (type $t (sub resource))) 1002 (export "[constructor]t" (func (param "x" u32) (result (own $t)))) 1003 (export "[method]t.assert" (func (param "self" (borrow $t)) (param "x" u32))) 1004 (export "[static]t.assert-own" (func (param "self" (own $t)) (param "x" u32))) 1005 )) 1006 1007 (alias export $i "t" (type $t)) 1008 (alias export $i "[constructor]t" (func $ctor)) 1009 (alias export $i "[method]t.assert" (func $assert-borrow)) 1010 (alias export $i "[static]t.assert-own" (func $assert-own)) 1011 1012 (core func $ctor (canon lower (func $ctor))) 1013 (core func $dtor (canon resource.drop $t)) 1014 (core func $assert-own (canon lower (func $assert-own))) 1015 (core func $assert-borrow (canon lower (func $assert-borrow))) 1016 1017 (core module $m 1018 (import "" "ctor" (func $ctor (param i32) (result i32))) 1019 (import "" "dtor" (func $dtor (param i32))) 1020 (import "" "assert-own" (func $assert-own (param i32 i32))) 1021 (import "" "assert-borrow" (func $assert-borrow (param i32 i32))) 1022 1023 (func (export "f") 1024 (local $r1 i32) 1025 (local $r2 i32) 1026 1027 (local.set $r1 (call $ctor (i32.const 100))) 1028 (local.set $r2 (call $ctor (i32.const 200))) 1029 1030 (if (i32.ne (local.get $r1) (i32.const 1)) (then (unreachable))) 1031 (if (i32.ne (local.get $r2) (i32.const 2)) (then (unreachable))) 1032 1033 (call $assert-borrow (local.get $r2) (i32.const 200)) 1034 (call $assert-borrow (local.get $r1) (i32.const 100)) 1035 1036 (call $assert-own (local.get $r2) (i32.const 200)) 1037 (call $dtor (local.get $r1)) 1038 ) 1039 ) 1040 (core instance $i (instantiate $m 1041 (with "" (instance 1042 (export "ctor" (func $ctor)) 1043 (export "dtor" (func $dtor)) 1044 (export "assert-own" (func $assert-own)) 1045 (export "assert-borrow" (func $assert-borrow)) 1046 )) 1047 )) 1048 (func (export "f") (canon lift (core func $i "f"))) 1049 ) 1050 (instance $b (instantiate $B (with "a" (instance $a)))) 1051 (export "f" (func $b "f")) 1052) 1053 1054(assert_return (invoke "f")) 1055 1056;; Test destructor behavior when using the wrong resource type 1057(component definition $C 1058 (type $r1 (resource (rep i32))) 1059 (type $r2 (resource (rep i32))) 1060 1061 (core func $drop1 (canon resource.drop $r1)) 1062 (core func $drop2 (canon resource.drop $r2)) 1063 (core func $new1 (canon resource.new $r1)) 1064 (core func $new2 (canon resource.new $r2)) 1065 1066 (core module $m2 1067 (import "" "drop1" (func $drop1 (param i32))) 1068 (import "" "drop2" (func $drop2 (param i32))) 1069 (import "" "new1" (func $new1 (param i32) (result i32))) 1070 (import "" "new2" (func $new2 (param i32) (result i32))) 1071 1072 (func (export "drop-r1-as-r2") (call $drop2 (call $new1 (i32.const 100)))) 1073 (func (export "return-r1-as-r2") (result i32) (call $new1 (i32.const 100))) 1074 ) 1075 1076 (core instance $i2 (instantiate $m2 1077 (with "" (instance 1078 (export "drop1" (func $drop1)) 1079 (export "drop2" (func $drop2)) 1080 (export "new1" (func $new1)) 1081 (export "new2" (func $new2)) 1082 )) 1083 )) 1084 1085 (export $r2' "r2" (type $r2)) 1086 (func (export "drop-r1-as-r2") (canon lift (core func $i2 "drop-r1-as-r2"))) 1087 (func (export "return-r1-as-r2") (result (own $r2')) (canon lift (core func $i2 "return-r1-as-r2"))) 1088) 1089 1090(component instance $C1 $C) 1091(assert_trap (invoke "drop-r1-as-r2") "handle index 1 used with the wrong type, expected guest-defined resource but found a different guest-defined resource") 1092(component instance $C1 $C) 1093(assert_trap (invoke "return-r1-as-r2") "handle index 1 used with the wrong type, expected guest-defined resource but found a different guest-defined resource") 1094 1095;; Test that `resource.rep` is exempt from may-leave checks 1096(component 1097 (type $r (resource (rep i32))) 1098 (core func $resource.new (canon resource.new $r)) 1099 (core func $resource.rep (canon resource.rep $r)) 1100 1101 (core module $DM 1102 (import "" "resource.new" (func $resource.new (param i32) (result i32))) 1103 (import "" "resource.rep" (func $resource.rep (param i32) (result i32))) 1104 1105 (global $g (mut i32) (i32.const 0)) 1106 1107 (func (export "run") 1108 (global.set $g (call $resource.new (i32.const 42))) 1109 ) 1110 (func (export "post-return") 1111 (i32.eq 1112 (call $resource.rep (global.get $g)) 1113 (i32.const 42)) 1114 if return end 1115 unreachable 1116 ) 1117 ) 1118 (core instance $dm (instantiate $DM (with "" (instance 1119 (export "resource.new" (func $resource.new)) 1120 (export "resource.rep" (func $resource.rep)) 1121 )))) 1122 (func (export "run") 1123 (canon lift (core func $dm "run") (post-return (func $dm "post-return")))) 1124) 1125 1126(assert_return (invoke "run")) 1127