wardite 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Steepfile +1 -0
- data/exe/wardite +11 -5
- data/lib/wardite/instruction.rb +7 -9
- data/lib/wardite/load.rb +14 -9
- data/lib/wardite/revisitor.rb +1 -1
- data/lib/wardite/value.rb +6 -22
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi/consts.rb +129 -0
- data/lib/wardite/wasi.rb +268 -7
- data/lib/wardite/wasm_module.rb +53 -0
- data/lib/wardite.rb +68 -40
- data/misc/proposals/rubykaigi2025.md +46 -0
- data/misc/slides/fib.c +4 -0
- data/misc/slides/fib.html +13 -0
- data/misc/slides/image-1.png +0 -0
- data/misc/slides/image-2.png +0 -0
- data/misc/slides/image.png +0 -0
- data/misc/slides/tokyo12.html +614 -0
- data/misc/slides/tokyo12.md +624 -0
- data/sig/fcntl.rbs +7 -0
- data/sig/generated/wardite/load.rbs +2 -2
- data/sig/generated/wardite/value.rbs +3 -10
- data/sig/generated/wardite/wasi/consts.rbs +137 -0
- data/sig/generated/wardite/wasi.rbs +62 -5
- data/sig/generated/wardite/wasm_module.rbs +42 -0
- data/sig/generated/wardite.rbs +24 -9
- metadata +15 -3
- data/examples/add.wasm +0 -0
@@ -0,0 +1,614 @@
|
|
1
|
+
<!DOCTYPE html><html lang="ja-JP"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0"><meta name="apple-mobile-web-app-capable" content="yes"><meta http-equiv="X-UA-Compatible" content="ie=edge"><meta property="og:type" content="website"><meta name="twitter:card" content="summary"><style>@media screen{body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button{appearance:none;background-color:initial;border:0;color:inherit;cursor:pointer;font-size:inherit;opacity:.8;outline:none;padding:0;transition:opacity .2s linear;-webkit-tap-highlight-color:transparent}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:disabled,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:disabled,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:disabled,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:disabled{cursor:not-allowed;opacity:.15!important}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:hover,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:hover,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:hover,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:hover{opacity:1}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:active,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:active,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:hover:active,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:hover:active{opacity:.6}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:not(:disabled),body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:not(:disabled),body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:hover:not(:disabled),body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:hover:not(:disabled){transition:none}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev],body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button.bespoke-marp-presenter-info-page-prev{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNNjggOTAgMjggNTBsNDAtNDAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button.bespoke-marp-presenter-info-page-next{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJtMzIgOTAgNDAtNDAtNDAtNDAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen]{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48ZGVmcz48c3R5bGU+LmF7ZmlsbDpub25lO3N0cm9rZTojZmZmO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NXB4fTwvc3R5bGU+PC9kZWZzPjxyZWN0IHdpZHRoPSI4MCIgaGVpZ2h0PSI2MCIgeD0iMTAiIHk9IjIwIiBjbGFzcz0iYSIgcng9IjUuNjciLz48cGF0aCBkPSJNNDAgNzBIMjBWNTBtMjAgMEwyMCA3MG00MC00MGgyMHYyMG0tMjAgMCAyMC0yMCIgY2xhc3M9ImEiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button.exit[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button.exit[data-bespoke-marp-osc=fullscreen]{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48ZGVmcz48c3R5bGU+LmF7ZmlsbDpub25lO3N0cm9rZTojZmZmO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NXB4fTwvc3R5bGU+PC9kZWZzPjxyZWN0IHdpZHRoPSI4MCIgaGVpZ2h0PSI2MCIgeD0iMTAiIHk9IjIwIiBjbGFzcz0iYSIgcng9IjUuNjciLz48cGF0aCBkPSJNMjAgNTBoMjB2MjBtLTIwIDAgMjAtMjBtNDAgMEg2MFYzMG0yMCAwTDYwIDUwIiBjbGFzcz0iYSIvPjwvc3ZnPg==")}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter]{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNODcuOCA0Ny41Qzg5IDUwIDg3LjcgNTIgODUgNTJIMzVhOC43IDguNyAwIDAgMS03LjItNC41bC0xNS42LTMxQzExIDE0IDEyLjIgMTIgMTUgMTJoNTBhOC44IDguOCAwIDAgMSA3LjIgNC41ek02MCA1MnYzNm0tMTAgMGgyME00NSA0MmgyMCIvPjwvc3ZnPg==") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button.bespoke-marp-presenter-note-bigger{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNMTIgNTBoODBNNTIgOTBWMTAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button.bespoke-marp-presenter-note-smaller{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNMTIgNTBoODAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}}@keyframes __bespoke_marp_transition_reduced_outgoing__{0%{opacity:1}to{opacity:0}}@keyframes __bespoke_marp_transition_reduced_incoming__{0%{mix-blend-mode:plus-lighter;opacity:0}to{mix-blend-mode:plus-lighter;opacity:1}}.bespoke-marp-note,.bespoke-marp-osc,.bespoke-progress-parent{display:none;transition:none}@media screen{::view-transition-group(*){animation-duration:var(--marp-bespoke-transition-animation-duration,.5s);animation-timing-function:ease}::view-transition-new(*),::view-transition-old(*){animation-delay:0s;animation-direction:var(--marp-bespoke-transition-animation-direction,normal);animation-duration:var(--marp-bespoke-transition-animation-duration,.5s);animation-fill-mode:both;animation-name:var(--marp-bespoke-transition-animation-name,var(--marp-bespoke-transition-animation-name-fallback,__bespoke_marp_transition_no_animation__));mix-blend-mode:normal}::view-transition-old(*){--marp-bespoke-transition-animation-name-fallback:__bespoke_marp_transition_reduced_outgoing__;animation-timing-function:ease}::view-transition-new(*){--marp-bespoke-transition-animation-name-fallback:__bespoke_marp_transition_reduced_incoming__;animation-timing-function:ease}::view-transition-new(root),::view-transition-old(root){animation-timing-function:linear}::view-transition-new(__bespoke_marp_transition_osc__),::view-transition-old(__bespoke_marp_transition_osc__){animation-duration:0s!important;animation-name:__bespoke_marp_transition_osc__!important}::view-transition-new(__bespoke_marp_transition_osc__){opacity:0!important}.bespoke-marp-transition-warming-up::view-transition-group(*),.bespoke-marp-transition-warming-up::view-transition-new(*),.bespoke-marp-transition-warming-up::view-transition-old(*){animation-play-state:paused!important}body,html{height:100%;margin:0}body{background:#000;overflow:hidden}svg.bespoke-marp-slide{content-visibility:hidden;opacity:0;pointer-events:none;z-index:-1}svg.bespoke-marp-slide:not(.bespoke-marp-active) *{view-transition-name:none!important}svg.bespoke-marp-slide.bespoke-marp-active{content-visibility:visible;opacity:1;pointer-events:auto;z-index:0}svg.bespoke-marp-slide.bespoke-marp-active.bespoke-marp-active-ready *{animation-name:__bespoke_marp__!important}@supports not (content-visibility:hidden){svg.bespoke-marp-slide[data-bespoke-marp-load=hideable]{display:none}svg.bespoke-marp-slide[data-bespoke-marp-load=hideable].bespoke-marp-active{display:block}}}@media screen and (prefers-reduced-motion:reduce){svg.bespoke-marp-slide *{view-transition-name:none!important}}@media screen{[data-bespoke-marp-fragment=inactive]{visibility:hidden}body[data-bespoke-view=""] .bespoke-marp-parent,body[data-bespoke-view=next] .bespoke-marp-parent{inset:0;position:absolute}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc{background:#000000a6;border-radius:7px;bottom:50px;color:#fff;contain:paint;display:block;font-family:Helvetica,Arial,sans-serif;font-size:16px;left:50%;line-height:0;opacity:1;padding:12px;position:absolute;touch-action:manipulation;transform:translateX(-50%);transition:opacity .2s linear;-webkit-user-select:none;user-select:none;white-space:nowrap;will-change:transform;z-index:1;view-transition-name:__bespoke_marp_transition_osc__}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>*,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>*{margin-left:6px}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>:first-child,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>:first-child{margin-left:0}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>span,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>span{opacity:.8}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>span[data-bespoke-marp-osc=page],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>span[data-bespoke-marp-osc=page]{display:inline-block;min-width:140px;text-align:center}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter],body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev]{height:32px;line-height:32px;width:32px}body[data-bespoke-view=""] .bespoke-marp-parent.bespoke-marp-inactive,body[data-bespoke-view=next] .bespoke-marp-parent.bespoke-marp-inactive{cursor:none}body[data-bespoke-view=""] .bespoke-marp-parent.bespoke-marp-inactive>.bespoke-marp-osc,body[data-bespoke-view=next] .bespoke-marp-parent.bespoke-marp-inactive>.bespoke-marp-osc{opacity:0;pointer-events:none}body[data-bespoke-view=""] svg.bespoke-marp-slide,body[data-bespoke-view=next] svg.bespoke-marp-slide{height:100%;left:0;position:absolute;top:0;width:100%}body[data-bespoke-view=""] .bespoke-progress-parent{background:#222;display:flex;height:5px;width:100%}body[data-bespoke-view=""] .bespoke-progress-parent+.bespoke-marp-parent{top:5px}body[data-bespoke-view=""] .bespoke-progress-parent .bespoke-progress-bar{background:#0288d1;flex:0 0 0;transition:flex-basis .2s cubic-bezier(0,1,1,1)}body[data-bespoke-view=next]{background:#0000}body[data-bespoke-view=presenter]{background:#161616}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container{display:grid;font-family:Helvetica,Arial,sans-serif;grid-template:"current dragbar next" minmax(140px,1fr) "current dragbar note" 2fr "info dragbar note" 3em;grid-template-columns:minmax(3px,var(--bespoke-marp-presenter-split-ratio,66%)) 0 minmax(3px,1fr);height:100%;left:0;position:absolute;top:0;width:100%}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-parent{grid-area:current;overflow:hidden;position:relative}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-parent svg.bespoke-marp-slide{height:calc(100% - 40px);left:20px;pointer-events:none;position:absolute;top:20px;-webkit-user-select:none;user-select:none;width:calc(100% - 40px)}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-parent svg.bespoke-marp-slide.bespoke-marp-active{filter:drop-shadow(0 3px 10px rgba(0,0,0,.5))}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-dragbar-container{background:#0288d1;cursor:col-resize;grid-area:dragbar;margin-left:-3px;opacity:0;position:relative;transition:opacity .4s linear .1s;width:6px;z-index:10}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-dragbar-container:hover{opacity:1}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-dragbar-container.active{opacity:1;transition-delay:0s}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-next-container{background:#222;cursor:pointer;display:none;grid-area:next;overflow:hidden;position:relative}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-next-container.active{display:block}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-next-container iframe.bespoke-marp-presenter-next{background:#0000;border:0;display:block;filter:drop-shadow(0 3px 10px rgba(0,0,0,.5));height:calc(100% - 40px);left:20px;pointer-events:none;position:absolute;top:20px;-webkit-user-select:none;user-select:none;width:calc(100% - 40px)}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container{background:#222;color:#eee;grid-area:note;position:relative;z-index:1}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button{height:1.5em;line-height:1.5em;width:1.5em}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-wrapper{display:block;inset:0;position:absolute}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-buttons{background:#000000a6;border-radius:4px;bottom:0;display:flex;gap:4px;margin:12px;opacity:0;padding:6px;pointer-events:none;position:absolute;right:0;transition:opacity .2s linear}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-buttons:focus-within,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-wrapper:focus-within+.bespoke-marp-presenter-note-buttons,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container:hover .bespoke-marp-presenter-note-buttons{opacity:1;pointer-events:auto}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note{box-sizing:border-box;font-size:calc(1.1em*var(--bespoke-marp-note-font-scale, 1));height:calc(100% - 40px);margin:20px;overflow:auto;padding-right:3px;white-space:pre-wrap;width:calc(100% - 40px);word-wrap:break-word;scrollbar-color:#eeeeee80 #0000;scrollbar-width:thin}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note::-webkit-scrollbar{width:6px}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note::-webkit-scrollbar-track{background:#0000}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note::-webkit-scrollbar-thumb{background:#eeeeee80;border-radius:6px}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note:empty{pointer-events:none}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note.active{display:block}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note p:first-child{margin-top:0}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note p:last-child{margin-bottom:0}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container{align-items:center;box-sizing:border-box;color:#eee;display:flex;flex-wrap:nowrap;grid-area:info;justify-content:center;overflow:hidden;padding:0 10px}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-page,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-time,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-timer{box-sizing:border-box;display:block;padding:0 10px;white-space:nowrap;width:100%}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button{height:1.5em;line-height:1.5em;width:1.5em}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-page{order:2;text-align:center}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-page .bespoke-marp-presenter-info-page-text{display:inline-block;min-width:120px;text-align:center}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-time{color:#999;order:1;text-align:left}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-timer{color:#999;order:3;text-align:right}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-timer:hover{cursor:pointer}}@media print{.bespoke-marp-presenter-info-container,.bespoke-marp-presenter-next-container,.bespoke-marp-presenter-note-container{display:none}}</style><style>div#\:\$p > svg > foreignObject > section{width:1280px;height:720px;box-sizing:border-box;overflow:hidden;position:relative;scroll-snap-align:center center;-webkit-text-size-adjust:100%;text-size-adjust:100%}div#\:\$p > svg > foreignObject > section::after{bottom:0;content:attr(data-marpit-pagination);padding:inherit;pointer-events:none;position:absolute;right:0}div#\:\$p > svg > foreignObject > section:not([data-marpit-pagination])::after{display:none}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1){font-size:2em;margin:0.67em 0}div#\:\$p > svg > foreignObject > section video::-webkit-media-controls{will-change:transform}@page {size:1280px 720px;margin:0}@media print{html, body{background-color:#fff;margin:0;page-break-inside:avoid;break-inside:avoid-page}div#\:\$p > svg > foreignObject > section{page-break-before:always;break-before:page}div#\:\$p > svg > foreignObject > section, div#\:\$p > svg > foreignObject > section *{-webkit-print-color-adjust:exact!important;animation-delay:0s!important;animation-duration:0s!important;color-adjust:exact!important;transition:none!important}div#\:\$p > svg[data-marpit-svg]{display:block;height:100vh;width:100vw}}div#\:\$p > svg > foreignObject > :where(section){container-type:size}div#\:\$p > svg > foreignObject > section img[data-marp-twemoji]{background:transparent;height:1em;margin:0 .05em 0 .1em;vertical-align:-.1em;width:1em}/*!
|
2
|
+
* Marp default theme.
|
3
|
+
*
|
4
|
+
* @theme default
|
5
|
+
* @author Yuki Hattori
|
6
|
+
*
|
7
|
+
* @auto-scaling true
|
8
|
+
* @size 16:9 1280px 720px
|
9
|
+
* @size 4:3 960px 720px
|
10
|
+
*/div#\:\$p > svg > foreignObject > section{--base-size-4:calc(var(--marpit-root-font-size, 1rem) * 0.25);--base-size-8:calc(var(--marpit-root-font-size, 1rem) * 0.5);--base-size-16:calc(var(--marpit-root-font-size, 1rem) * 1);--base-size-24:calc(var(--marpit-root-font-size, 1rem) * 1.5);--base-size-40:calc(var(--marpit-root-font-size, 1rem) * 2.5);--base-text-weight-normal:400;--base-text-weight-medium:500;--base-text-weight-semibold:600;--fontStack-monospace:ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;--fgColor-accent:Highlight;}div#\:\$p > svg > foreignObject > section [data-theme=light],div#\:\$p > svg > foreignObject > section{color-scheme:light;--focus-outlineColor:#0969da;--fgColor-default:#1f2328;--fgColor-muted:#59636e;--fgColor-accent:#0969da;--fgColor-success:#1a7f37;--fgColor-attention:#9a6700;--fgColor-danger:#d1242f;--fgColor-done:#8250df;--bgColor-default:#fff;--bgColor-muted:#f6f8fa;--bgColor-neutral-muted:#818b981f;--bgColor-attention-muted:#fff8c5;--borderColor-default:#d1d9e0;--borderColor-muted:#d1d9e0b3;--borderColor-neutral-muted:#d1d9e0b3;--borderColor-accent-emphasis:#0969da;--borderColor-success-emphasis:#1a7f37;--borderColor-attention-emphasis:#9a6700;--borderColor-danger-emphasis:#cf222e;--borderColor-done-emphasis:#8250df;--color-prettylights-syntax-comment:#59636e;--color-prettylights-syntax-constant:#0550ae;--color-prettylights-syntax-constant-other-reference-link:#0a3069;--color-prettylights-syntax-entity:#6639ba;--color-prettylights-syntax-storage-modifier-import:#1f2328;--color-prettylights-syntax-entity-tag:#0550ae;--color-prettylights-syntax-keyword:#cf222e;--color-prettylights-syntax-string:#0a3069;--color-prettylights-syntax-variable:#953800;--color-prettylights-syntax-brackethighlighter-unmatched:#82071e;--color-prettylights-syntax-brackethighlighter-angle:#59636e;--color-prettylights-syntax-invalid-illegal-text:#f6f8fa;--color-prettylights-syntax-invalid-illegal-bg:#82071e;--color-prettylights-syntax-carriage-return-text:#f6f8fa;--color-prettylights-syntax-carriage-return-bg:#cf222e;--color-prettylights-syntax-string-regexp:#116329;--color-prettylights-syntax-markup-list:#3b2300;--color-prettylights-syntax-markup-heading:#0550ae;--color-prettylights-syntax-markup-italic:#1f2328;--color-prettylights-syntax-markup-bold:#1f2328;--color-prettylights-syntax-markup-deleted-text:#82071e;--color-prettylights-syntax-markup-deleted-bg:#ffebe9;--color-prettylights-syntax-markup-inserted-text:#116329;--color-prettylights-syntax-markup-inserted-bg:#dafbe1;--color-prettylights-syntax-markup-changed-text:#953800;--color-prettylights-syntax-markup-changed-bg:#ffd8b5;--color-prettylights-syntax-markup-ignored-text:#d1d9e0;--color-prettylights-syntax-markup-ignored-bg:#0550ae;--color-prettylights-syntax-meta-diff-range:#8250df;--color-prettylights-syntax-sublimelinter-gutter-mark:#818b98;}div#\:\$p > svg > foreignObject > section [data-theme=dark],div#\:\$p > svg > foreignObject > section:where(.invert){color-scheme:dark;--focus-outlineColor:#1f6feb;--fgColor-default:#f0f6fc;--fgColor-muted:#9198a1;--fgColor-accent:#4493f8;--fgColor-success:#3fb950;--fgColor-attention:#d29922;--fgColor-danger:#f85149;--fgColor-done:#ab7df8;--bgColor-default:#0d1117;--bgColor-muted:#151b23;--bgColor-neutral-muted:#656c7633;--bgColor-attention-muted:#bb800926;--borderColor-default:#3d444d;--borderColor-muted:#3d444db3;--borderColor-neutral-muted:#3d444db3;--borderColor-accent-emphasis:#1f6feb;--borderColor-success-emphasis:#238636;--borderColor-attention-emphasis:#9e6a03;--borderColor-danger-emphasis:#da3633;--borderColor-done-emphasis:#8957e5;--color-prettylights-syntax-comment:#9198a1;--color-prettylights-syntax-constant:#79c0ff;--color-prettylights-syntax-constant-other-reference-link:#a5d6ff;--color-prettylights-syntax-entity:#d2a8ff;--color-prettylights-syntax-storage-modifier-import:#f0f6fc;--color-prettylights-syntax-entity-tag:#7ee787;--color-prettylights-syntax-keyword:#ff7b72;--color-prettylights-syntax-string:#a5d6ff;--color-prettylights-syntax-variable:#ffa657;--color-prettylights-syntax-brackethighlighter-unmatched:#f85149;--color-prettylights-syntax-brackethighlighter-angle:#9198a1;--color-prettylights-syntax-invalid-illegal-text:#f0f6fc;--color-prettylights-syntax-invalid-illegal-bg:#8e1519;--color-prettylights-syntax-carriage-return-text:#f0f6fc;--color-prettylights-syntax-carriage-return-bg:#b62324;--color-prettylights-syntax-string-regexp:#7ee787;--color-prettylights-syntax-markup-list:#f2cc60;--color-prettylights-syntax-markup-heading:#1f6feb;--color-prettylights-syntax-markup-italic:#f0f6fc;--color-prettylights-syntax-markup-bold:#f0f6fc;--color-prettylights-syntax-markup-deleted-text:#ffdcd7;--color-prettylights-syntax-markup-deleted-bg:#67060c;--color-prettylights-syntax-markup-inserted-text:#aff5b4;--color-prettylights-syntax-markup-inserted-bg:#033a16;--color-prettylights-syntax-markup-changed-text:#ffdfb6;--color-prettylights-syntax-markup-changed-bg:#5a1e02;--color-prettylights-syntax-markup-ignored-text:#f0f6fc;--color-prettylights-syntax-markup-ignored-bg:#1158c7;--color-prettylights-syntax-meta-diff-range:#d2a8ff;--color-prettylights-syntax-sublimelinter-gutter-mark:#3d444d;}div#\:\$p > svg > foreignObject > section{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;background-color:var(--bgColor-default);color:var(--fgColor-default);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Noto Sans,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;font-size:16px;line-height:1.5;margin:0;word-wrap:break-word}div#\:\$p > svg > foreignObject > section{--marpit-root-font-size:16px;}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1):hover .anchor .octicon-link:before,div#\:\$p > svg > foreignObject > section :is(h2, marp-h2):hover .anchor .octicon-link:before,div#\:\$p > svg > foreignObject > section :is(h3, marp-h3):hover .anchor .octicon-link:before,div#\:\$p > svg > foreignObject > section :is(h4, marp-h4):hover .anchor .octicon-link:before,div#\:\$p > svg > foreignObject > section :is(h5, marp-h5):hover .anchor .octicon-link:before,div#\:\$p > svg > foreignObject > section :is(h6, marp-h6):hover .anchor .octicon-link:before{background-color:currentColor;content:" ";display:inline-block;height:16px;-webkit-mask-image:url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 0 0 1.06 1.06l1.25-1.25a2 2 0 1 1 2.83 2.83l-2.5 2.5a2 2 0 0 1-2.83 0 .75.75 0 0 0-1.06 1.06 3.5 3.5 0 0 0 4.95 0l2.5-2.5a3.5 3.5 0 0 0-4.95-4.95zm-4.69 9.64a2 2 0 0 1 0-2.83l2.5-2.5a2 2 0 0 1 2.83 0 .75.75 0 0 0 1.06-1.06 3.5 3.5 0 0 0-4.95 0l-2.5 2.5a3.5 3.5 0 0 0 4.95 4.95l1.25-1.25a.75.75 0 0 0-1.06-1.06l-1.25 1.25a2 2 0 0 1-2.83 0"/></svg>');mask-image:url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 0 0 1.06 1.06l1.25-1.25a2 2 0 1 1 2.83 2.83l-2.5 2.5a2 2 0 0 1-2.83 0 .75.75 0 0 0-1.06 1.06 3.5 3.5 0 0 0 4.95 0l2.5-2.5a3.5 3.5 0 0 0-4.95-4.95zm-4.69 9.64a2 2 0 0 1 0-2.83l2.5-2.5a2 2 0 0 1 2.83 0 .75.75 0 0 0 1.06-1.06 3.5 3.5 0 0 0-4.95 0l-2.5 2.5a3.5 3.5 0 0 0 4.95 4.95l1.25-1.25a.75.75 0 0 0-1.06-1.06l-1.25 1.25a2 2 0 0 1-2.83 0"/></svg>');width:16px}div#\:\$p > svg > foreignObject > section details,div#\:\$p > svg > foreignObject > section figcaption,div#\:\$p > svg > foreignObject > section figure{display:block}div#\:\$p > svg > foreignObject > section summary{display:list-item}div#\:\$p > svg > foreignObject > section [hidden]{display:none!important}div#\:\$p > svg > foreignObject > section a{background-color:transparent;color:var(--fgColor-accent);text-decoration:none}div#\:\$p > svg > foreignObject > section abbr[title]{border-bottom:none;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}div#\:\$p > svg > foreignObject > section b,div#\:\$p > svg > foreignObject > section strong{font-weight:var(--base-text-weight-semibold, 600)}div#\:\$p > svg > foreignObject > section dfn{font-style:italic}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1){border-bottom:1px solid var(--borderColor-muted);font-size:2em;font-weight:var(--base-text-weight-semibold, 600);margin:.67em 0;padding-bottom:.3em}div#\:\$p > svg > foreignObject > section mark{background-color:var(--bgColor-attention-muted);color:var(--fgColor-default)}div#\:\$p > svg > foreignObject > section small{font-size:90%}div#\:\$p > svg > foreignObject > section sub,div#\:\$p > svg > foreignObject > section sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}div#\:\$p > svg > foreignObject > section sub{bottom:-.25em}div#\:\$p > svg > foreignObject > section sup{top:-.5em}div#\:\$p > svg > foreignObject > section img{border-style:none;box-sizing:content-box;max-width:100%}div#\:\$p > svg > foreignObject > section code,div#\:\$p > svg > foreignObject > section kbd,div#\:\$p > svg > foreignObject > section :is(pre, marp-pre),div#\:\$p > svg > foreignObject > section samp{font-family:monospace;font-size:1em}div#\:\$p > svg > foreignObject > section figure{margin:1em var(--base-size-40)}div#\:\$p > svg > foreignObject > section hr{background:transparent;background-color:var(--borderColor-default);border:0;box-sizing:content-box;height:.25em;margin:var(--base-size-24) 0;overflow:hidden;padding:0}div#\:\$p > svg > foreignObject > section input{font:inherit;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible}div#\:\$p > svg > foreignObject > section [type=button],div#\:\$p > svg > foreignObject > section [type=reset],div#\:\$p > svg > foreignObject > section [type=submit]{-webkit-appearance:button;-moz-appearance:button;appearance:button}div#\:\$p > svg > foreignObject > section [type=checkbox],div#\:\$p > svg > foreignObject > section [type=radio]{box-sizing:border-box;padding:0}div#\:\$p > svg > foreignObject > section [type=number]::-webkit-inner-spin-button,div#\:\$p > svg > foreignObject > section [type=number]::-webkit-outer-spin-button{height:auto}div#\:\$p > svg > foreignObject > section [type=search]::-webkit-search-cancel-button,div#\:\$p > svg > foreignObject > section [type=search]::-webkit-search-decoration{-webkit-appearance:none;appearance:none}div#\:\$p > svg > foreignObject > section ::-webkit-input-placeholder{color:inherit;opacity:.54}div#\:\$p > svg > foreignObject > section ::-webkit-file-upload-button{-webkit-appearance:button;appearance:button;font:inherit}div#\:\$p > svg > foreignObject > section a:hover{text-decoration:underline}div#\:\$p > svg > foreignObject > section ::-moz-placeholder{color:var(--fgColor-muted);opacity:1}div#\:\$p > svg > foreignObject > section ::placeholder{color:var(--fgColor-muted);opacity:1}div#\:\$p > svg > foreignObject > section hr:after,div#\:\$p > svg > foreignObject > section hr:before{content:"";display:table}div#\:\$p > svg > foreignObject > section hr:after{clear:both}div#\:\$p > svg > foreignObject > section table{border-collapse:collapse;border-spacing:0;display:block;font-variant:tabular-nums;max-width:100%;overflow:auto;width:-moz-max-content;width:max-content}div#\:\$p > svg > foreignObject > section td,div#\:\$p > svg > foreignObject > section th{padding:0}div#\:\$p > svg > foreignObject > section details summary{cursor:pointer}div#\:\$p > svg > foreignObject > section [role=button]:focus,div#\:\$p > svg > foreignObject > section a:focus,div#\:\$p > svg > foreignObject > section input[type=checkbox]:focus,div#\:\$p > svg > foreignObject > section input[type=radio]:focus{box-shadow:none;outline:2px solid var(--focus-outlineColor);outline-offset:-2px}div#\:\$p > svg > foreignObject > section [role=button]:focus:not(:focus-visible),div#\:\$p > svg > foreignObject > section a:focus:not(:focus-visible),div#\:\$p > svg > foreignObject > section input[type=checkbox]:focus:not(:focus-visible),div#\:\$p > svg > foreignObject > section input[type=radio]:focus:not(:focus-visible){outline:1px solid transparent}div#\:\$p > svg > foreignObject > section [role=button]:focus-visible,div#\:\$p > svg > foreignObject > section a:focus-visible,div#\:\$p > svg > foreignObject > section input[type=checkbox]:focus-visible,div#\:\$p > svg > foreignObject > section input[type=radio]:focus-visible{box-shadow:none;outline:2px solid var(--focus-outlineColor);outline-offset:-2px}div#\:\$p > svg > foreignObject > section a:not([class]):focus,div#\:\$p > svg > foreignObject > section a:not([class]):focus-visible,div#\:\$p > svg > foreignObject > section input[type=checkbox]:focus,div#\:\$p > svg > foreignObject > section input[type=checkbox]:focus-visible,div#\:\$p > svg > foreignObject > section input[type=radio]:focus,div#\:\$p > svg > foreignObject > section input[type=radio]:focus-visible{outline-offset:0}div#\:\$p > svg > foreignObject > section kbd{background-color:var(--bgColor-muted);border-bottom-color:var(--borderColor-neutral-muted);border:1px solid var(--borderColor-neutral-muted);border-radius:6px;box-shadow:inset 0 -1px 0 var(--borderColor-neutral-muted);color:var(--fgColor-default);display:inline-block;font:11px var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);line-height:10px;padding:var(--base-size-4);vertical-align:middle}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1),div#\:\$p > svg > foreignObject > section :is(h2, marp-h2),div#\:\$p > svg > foreignObject > section :is(h3, marp-h3),div#\:\$p > svg > foreignObject > section :is(h4, marp-h4),div#\:\$p > svg > foreignObject > section :is(h5, marp-h5),div#\:\$p > svg > foreignObject > section :is(h6, marp-h6){font-weight:var(--base-text-weight-semibold, 600);line-height:1.25;margin-bottom:var(--base-size-16);margin-top:var(--base-size-24)}div#\:\$p > svg > foreignObject > section :is(h2, marp-h2){border-bottom:1px solid var(--borderColor-muted);font-size:1.5em;padding-bottom:.3em}div#\:\$p > svg > foreignObject > section :is(h2, marp-h2),div#\:\$p > svg > foreignObject > section :is(h3, marp-h3){font-weight:var(--base-text-weight-semibold, 600)}div#\:\$p > svg > foreignObject > section :is(h3, marp-h3){font-size:1.25em}div#\:\$p > svg > foreignObject > section :is(h4, marp-h4){font-size:1em}div#\:\$p > svg > foreignObject > section :is(h4, marp-h4),div#\:\$p > svg > foreignObject > section :is(h5, marp-h5){font-weight:var(--base-text-weight-semibold, 600)}div#\:\$p > svg > foreignObject > section :is(h5, marp-h5){font-size:.875em}div#\:\$p > svg > foreignObject > section :is(h6, marp-h6){color:var(--fgColor-muted);font-size:.85em;font-weight:var(--base-text-weight-semibold, 600)}div#\:\$p > svg > foreignObject > section p{margin-bottom:10px;margin-top:0}div#\:\$p > svg > foreignObject > section blockquote{border-left:.25em solid var(--borderColor-default);color:var(--fgColor-muted);margin:0;padding:0 1em}div#\:\$p > svg > foreignObject > section ol,div#\:\$p > svg > foreignObject > section ul{margin-bottom:0;margin-top:0;padding-left:2em}div#\:\$p > svg > foreignObject > section ol ol,div#\:\$p > svg > foreignObject > section ul ol{list-style-type:lower-roman}div#\:\$p > svg > foreignObject > section ol ol ol,div#\:\$p > svg > foreignObject > section ol ul ol,div#\:\$p > svg > foreignObject > section ul ol ol,div#\:\$p > svg > foreignObject > section ul ul ol{list-style-type:lower-alpha}div#\:\$p > svg > foreignObject > section dd{margin-left:0}div#\:\$p > svg > foreignObject > section code,div#\:\$p > svg > foreignObject > section :is(pre, marp-pre),div#\:\$p > svg > foreignObject > section samp,div#\:\$p > svg > foreignObject > section tt{font-family:var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);font-size:12px}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre){margin-bottom:0;margin-top:0;word-wrap:normal}div#\:\$p > svg > foreignObject > section .octicon{display:inline-block;overflow:visible!important;vertical-align:text-bottom;fill:currentColor}div#\:\$p > svg > foreignObject > section input::-webkit-inner-spin-button,div#\:\$p > svg > foreignObject > section input::-webkit-outer-spin-button{-webkit-appearance:none;appearance:none;margin:0}div#\:\$p > svg > foreignObject > section .mr-2{margin-right:var(--base-size-8, 8px)!important}div#\:\$p > svg > foreignObject > section:after,div#\:\$p > svg > foreignObject > section:before{display:table}div#\:\$p > svg > foreignObject > section:after{clear:both}div#\:\$p > svg > foreignObject > section>:first-child{margin-top:0!important}div#\:\$p > svg > foreignObject > section>:last-child{margin-bottom:0!important}div#\:\$p > svg > foreignObject > section a:not([href]){color:inherit;text-decoration:none}div#\:\$p > svg > foreignObject > section .absent{color:var(--fgColor-danger)}div#\:\$p > svg > foreignObject > section .anchor{float:left;line-height:1;margin-left:-20px;padding-right:var(--base-size-4)}div#\:\$p > svg > foreignObject > section .anchor:focus{outline:none}div#\:\$p > svg > foreignObject > section blockquote,div#\:\$p > svg > foreignObject > section details,div#\:\$p > svg > foreignObject > section dl,div#\:\$p > svg > foreignObject > section ol,div#\:\$p > svg > foreignObject > section p,div#\:\$p > svg > foreignObject > section :is(pre, marp-pre),div#\:\$p > svg > foreignObject > section table,div#\:\$p > svg > foreignObject > section ul{margin-bottom:var(--base-size-16);margin-top:0}div#\:\$p > svg > foreignObject > section blockquote>:first-child{margin-top:0}div#\:\$p > svg > foreignObject > section blockquote>:last-child{margin-bottom:0}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1) .octicon-link,div#\:\$p > svg > foreignObject > section :is(h2, marp-h2) .octicon-link,div#\:\$p > svg > foreignObject > section :is(h3, marp-h3) .octicon-link,div#\:\$p > svg > foreignObject > section :is(h4, marp-h4) .octicon-link,div#\:\$p > svg > foreignObject > section :is(h5, marp-h5) .octicon-link,div#\:\$p > svg > foreignObject > section :is(h6, marp-h6) .octicon-link{color:var(--fgColor-default);vertical-align:middle;visibility:hidden}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1):hover .anchor,div#\:\$p > svg > foreignObject > section :is(h2, marp-h2):hover .anchor,div#\:\$p > svg > foreignObject > section :is(h3, marp-h3):hover .anchor,div#\:\$p > svg > foreignObject > section :is(h4, marp-h4):hover .anchor,div#\:\$p > svg > foreignObject > section :is(h5, marp-h5):hover .anchor,div#\:\$p > svg > foreignObject > section :is(h6, marp-h6):hover .anchor{text-decoration:none}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1):hover .anchor .octicon-link,div#\:\$p > svg > foreignObject > section :is(h2, marp-h2):hover .anchor .octicon-link,div#\:\$p > svg > foreignObject > section :is(h3, marp-h3):hover .anchor .octicon-link,div#\:\$p > svg > foreignObject > section :is(h4, marp-h4):hover .anchor .octicon-link,div#\:\$p > svg > foreignObject > section :is(h5, marp-h5):hover .anchor .octicon-link,div#\:\$p > svg > foreignObject > section :is(h6, marp-h6):hover .anchor .octicon-link{visibility:visible}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1) code,div#\:\$p > svg > foreignObject > section :is(h1, marp-h1) tt,div#\:\$p > svg > foreignObject > section :is(h2, marp-h2) code,div#\:\$p > svg > foreignObject > section :is(h2, marp-h2) tt,div#\:\$p > svg > foreignObject > section :is(h3, marp-h3) code,div#\:\$p > svg > foreignObject > section :is(h3, marp-h3) tt,div#\:\$p > svg > foreignObject > section :is(h4, marp-h4) code,div#\:\$p > svg > foreignObject > section :is(h4, marp-h4) tt,div#\:\$p > svg > foreignObject > section :is(h5, marp-h5) code,div#\:\$p > svg > foreignObject > section :is(h5, marp-h5) tt,div#\:\$p > svg > foreignObject > section :is(h6, marp-h6) code,div#\:\$p > svg > foreignObject > section :is(h6, marp-h6) tt{font-size:inherit;padding:0 .2em}div#\:\$p > svg > foreignObject > section summary :is(h1, marp-h1),div#\:\$p > svg > foreignObject > section summary :is(h2, marp-h2),div#\:\$p > svg > foreignObject > section summary :is(h3, marp-h3),div#\:\$p > svg > foreignObject > section summary :is(h4, marp-h4),div#\:\$p > svg > foreignObject > section summary :is(h5, marp-h5),div#\:\$p > svg > foreignObject > section summary :is(h6, marp-h6){display:inline-block}div#\:\$p > svg > foreignObject > section summary :is(h1, marp-h1) .anchor,div#\:\$p > svg > foreignObject > section summary :is(h2, marp-h2) .anchor,div#\:\$p > svg > foreignObject > section summary :is(h3, marp-h3) .anchor,div#\:\$p > svg > foreignObject > section summary :is(h4, marp-h4) .anchor,div#\:\$p > svg > foreignObject > section summary :is(h5, marp-h5) .anchor,div#\:\$p > svg > foreignObject > section summary :is(h6, marp-h6) .anchor{margin-left:-40px}div#\:\$p > svg > foreignObject > section summary :is(h1, marp-h1),div#\:\$p > svg > foreignObject > section summary :is(h2, marp-h2){border-bottom:0;padding-bottom:0}div#\:\$p > svg > foreignObject > section ol.no-list,div#\:\$p > svg > foreignObject > section ul.no-list{list-style-type:none;padding:0}div#\:\$p > svg > foreignObject > section ol[type="a s"]{list-style-type:lower-alpha}div#\:\$p > svg > foreignObject > section ol[type="A s"]{list-style-type:upper-alpha}div#\:\$p > svg > foreignObject > section ol[type="i s"]{list-style-type:lower-roman}div#\:\$p > svg > foreignObject > section ol[type="I s"]{list-style-type:upper-roman}div#\:\$p > svg > foreignObject > section div>ol:not([type]),div#\:\$p > svg > foreignObject > section ol[type="1"]{list-style-type:decimal}div#\:\$p > svg > foreignObject > section ol ol,div#\:\$p > svg > foreignObject > section ol ul,div#\:\$p > svg > foreignObject > section ul ol,div#\:\$p > svg > foreignObject > section ul ul{margin-bottom:0;margin-top:0}div#\:\$p > svg > foreignObject > section li>p{margin-top:var(--base-size-16)}div#\:\$p > svg > foreignObject > section li+li{margin-top:.25em}div#\:\$p > svg > foreignObject > section dl{padding:0}div#\:\$p > svg > foreignObject > section dl dt{font-size:1em;font-style:italic;font-weight:var(--base-text-weight-semibold, 600);margin-top:var(--base-size-16);padding:0}div#\:\$p > svg > foreignObject > section dl dd{margin-bottom:var(--base-size-16);padding:0 var(--base-size-16)}div#\:\$p > svg > foreignObject > section table th{font-weight:var(--base-text-weight-semibold, 600)}div#\:\$p > svg > foreignObject > section table td,div#\:\$p > svg > foreignObject > section table th{border:1px solid var(--borderColor-default);padding:6px 13px}div#\:\$p > svg > foreignObject > section table td>:last-child{margin-bottom:0}div#\:\$p > svg > foreignObject > section table tr{background-color:var(--bgColor-default);border-top:1px solid var(--borderColor-muted)}div#\:\$p > svg > foreignObject > section table tr:nth-child(2n){background-color:var(--bgColor-muted)}div#\:\$p > svg > foreignObject > section table img{background-color:transparent}div#\:\$p > svg > foreignObject > section img[align=right]{padding-left:20px}div#\:\$p > svg > foreignObject > section img[align=left]{padding-right:20px}div#\:\$p > svg > foreignObject > section .emoji{background-color:transparent;max-width:none;vertical-align:text-top}div#\:\$p > svg > foreignObject > section :is(span, marp-span).frame,div#\:\$p > svg > foreignObject > section :is(span, marp-span).frame>:is(span, marp-span){display:block;overflow:hidden}div#\:\$p > svg > foreignObject > section :is(span, marp-span).frame>:is(span, marp-span){border:1px solid var(--borderColor-default);float:left;margin:13px 0 0;padding:7px;width:auto}div#\:\$p > svg > foreignObject > section :is(span, marp-span).frame :is(span, marp-span) img{display:block;float:left}div#\:\$p > svg > foreignObject > section :is(span, marp-span).frame :is(span, marp-span) :is(span, marp-span){clear:both;color:var(--fgColor-default);display:block;padding:5px 0 0}div#\:\$p > svg > foreignObject > section :is(span, marp-span).align-center{clear:both;display:block;overflow:hidden}div#\:\$p > svg > foreignObject > section :is(span, marp-span).align-center>:is(span, marp-span){display:block;margin:13px auto 0;overflow:hidden;text-align:center}div#\:\$p > svg > foreignObject > section :is(span, marp-span).align-center :is(span, marp-span) img{margin:0 auto;text-align:center}div#\:\$p > svg > foreignObject > section :is(span, marp-span).align-right{clear:both;display:block;overflow:hidden}div#\:\$p > svg > foreignObject > section :is(span, marp-span).align-right>:is(span, marp-span){display:block;margin:13px 0 0;overflow:hidden;text-align:right}div#\:\$p > svg > foreignObject > section :is(span, marp-span).align-right :is(span, marp-span) img{margin:0;text-align:right}div#\:\$p > svg > foreignObject > section :is(span, marp-span).float-left{display:block;float:left;margin-right:13px;overflow:hidden}div#\:\$p > svg > foreignObject > section :is(span, marp-span).float-left :is(span, marp-span){margin:13px 0 0}div#\:\$p > svg > foreignObject > section :is(span, marp-span).float-right{display:block;float:right;margin-left:13px;overflow:hidden}div#\:\$p > svg > foreignObject > section :is(span, marp-span).float-right>:is(span, marp-span){display:block;margin:13px auto 0;overflow:hidden;text-align:right}div#\:\$p > svg > foreignObject > section code,div#\:\$p > svg > foreignObject > section tt{background-color:var(--bgColor-neutral-muted);border-radius:6px;font-size:85%;margin:0;padding:.2em .4em;white-space:break-spaces}div#\:\$p > svg > foreignObject > section code br,div#\:\$p > svg > foreignObject > section tt br{display:none}div#\:\$p > svg > foreignObject > section del code{text-decoration:inherit}div#\:\$p > svg > foreignObject > section samp{font-size:85%}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) code{font-size:100%}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre)>code{background:transparent;border:0;margin:0;padding:0;white-space:pre;word-break:normal}div#\:\$p > svg > foreignObject > section .highlight{margin-bottom:var(--base-size-16)}div#\:\$p > svg > foreignObject > section .highlight :is(pre, marp-pre){margin-bottom:0;word-break:normal}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre){background-color:var(--bgColor-muted);border-radius:6px;color:var(--fgColor-default);font-size:85%;line-height:1.45;overflow:auto;padding:var(--base-size-16)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) code,div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) tt{display:inline;line-height:inherit;margin:0;max-width:auto;overflow:visible;padding:0;word-wrap:normal;background-color:transparent;border:0}div#\:\$p > svg > foreignObject > section .csv-data td,div#\:\$p > svg > foreignObject > section .csv-data th{font-size:12px;line-height:1;overflow:hidden;padding:5px;text-align:left;white-space:nowrap}div#\:\$p > svg > foreignObject > section .csv-data .blob-num{background:var(--bgColor-default);border:0;padding:10px var(--base-size-8) 9px;text-align:right}div#\:\$p > svg > foreignObject > section .csv-data tr{border-top:0}div#\:\$p > svg > foreignObject > section .csv-data th{background:var(--bgColor-muted);border-top:0;font-weight:var(--base-text-weight-semibold, 600)}div#\:\$p > svg > foreignObject > section [data-footnote-ref]:before{content:"["}div#\:\$p > svg > foreignObject > section [data-footnote-ref]:after{content:"]"}div#\:\$p > svg > foreignObject > section .footnotes{border-top:1px solid var(--borderColor-default);color:var(--fgColor-muted);font-size:12px}div#\:\$p > svg > foreignObject > section div#\:\$p > svg > foreignObject > section section.footnotes{--marpit-root-font-size:12px;}div#\:\$p > svg > foreignObject > section .footnotes ol,div#\:\$p > svg > foreignObject > section .footnotes ol ul{padding-left:var(--base-size-16)}div#\:\$p > svg > foreignObject > section .footnotes ol ul{display:inline-block;margin-top:var(--base-size-16)}div#\:\$p > svg > foreignObject > section .footnotes li{position:relative}div#\:\$p > svg > foreignObject > section .footnotes li:target:before{border:2px solid var(--borderColor-accent-emphasis);border-radius:6px;bottom:calc(var(--base-size-8)*-1);content:"";left:calc(var(--base-size-24)*-1);pointer-events:none;position:absolute;right:calc(var(--base-size-8)*-1);top:calc(var(--base-size-8)*-1)}div#\:\$p > svg > foreignObject > section .footnotes li:target{color:var(--fgColor-default)}div#\:\$p > svg > foreignObject > section .footnotes .data-footnote-backref g-emoji{font-family:monospace}div#\:\$p > svg > foreignObject > section body:has(:modal){padding-right:var(--dialog-scrollgutter)!important}div#\:\$p > svg > foreignObject > section .pl-c{color:var(--color-prettylights-syntax-comment)}div#\:\$p > svg > foreignObject > section .pl-c1,div#\:\$p > svg > foreignObject > section .pl-s .pl-v{color:var(--color-prettylights-syntax-constant)}div#\:\$p > svg > foreignObject > section .pl-e,div#\:\$p > svg > foreignObject > section .pl-en{color:var(--color-prettylights-syntax-entity)}div#\:\$p > svg > foreignObject > section .pl-s .pl-s1,div#\:\$p > svg > foreignObject > section .pl-smi{color:var(--color-prettylights-syntax-storage-modifier-import)}div#\:\$p > svg > foreignObject > section .pl-ent{color:var(--color-prettylights-syntax-entity-tag)}div#\:\$p > svg > foreignObject > section .pl-k{color:var(--color-prettylights-syntax-keyword)}div#\:\$p > svg > foreignObject > section .pl-pds,div#\:\$p > svg > foreignObject > section .pl-s,div#\:\$p > svg > foreignObject > section .pl-s .pl-pse .pl-s1,div#\:\$p > svg > foreignObject > section .pl-sr,div#\:\$p > svg > foreignObject > section .pl-sr .pl-cce,div#\:\$p > svg > foreignObject > section .pl-sr .pl-sra,div#\:\$p > svg > foreignObject > section .pl-sr .pl-sre{color:var(--color-prettylights-syntax-string)}div#\:\$p > svg > foreignObject > section .pl-smw,div#\:\$p > svg > foreignObject > section .pl-v{color:var(--color-prettylights-syntax-variable)}div#\:\$p > svg > foreignObject > section .pl-bu{color:var(--color-prettylights-syntax-brackethighlighter-unmatched)}div#\:\$p > svg > foreignObject > section .pl-ii{background-color:var(--color-prettylights-syntax-invalid-illegal-bg);color:var(--color-prettylights-syntax-invalid-illegal-text)}div#\:\$p > svg > foreignObject > section .pl-c2{background-color:var(--color-prettylights-syntax-carriage-return-bg);color:var(--color-prettylights-syntax-carriage-return-text)}div#\:\$p > svg > foreignObject > section .pl-sr .pl-cce{color:var(--color-prettylights-syntax-string-regexp);font-weight:700}div#\:\$p > svg > foreignObject > section .pl-ml{color:var(--color-prettylights-syntax-markup-list)}div#\:\$p > svg > foreignObject > section .pl-mh,div#\:\$p > svg > foreignObject > section .pl-mh .pl-en,div#\:\$p > svg > foreignObject > section .pl-ms{color:var(--color-prettylights-syntax-markup-heading);font-weight:700}div#\:\$p > svg > foreignObject > section .pl-mi{color:var(--color-prettylights-syntax-markup-italic);font-style:italic}div#\:\$p > svg > foreignObject > section .pl-mb{color:var(--color-prettylights-syntax-markup-bold);font-weight:700}div#\:\$p > svg > foreignObject > section .pl-md{background-color:var(--color-prettylights-syntax-markup-deleted-bg);color:var(--color-prettylights-syntax-markup-deleted-text)}div#\:\$p > svg > foreignObject > section .pl-mi1{background-color:var(--color-prettylights-syntax-markup-inserted-bg);color:var(--color-prettylights-syntax-markup-inserted-text)}div#\:\$p > svg > foreignObject > section .pl-mc{background-color:var(--color-prettylights-syntax-markup-changed-bg);color:var(--color-prettylights-syntax-markup-changed-text)}div#\:\$p > svg > foreignObject > section .pl-mi2{background-color:var(--color-prettylights-syntax-markup-ignored-bg);color:var(--color-prettylights-syntax-markup-ignored-text)}div#\:\$p > svg > foreignObject > section .pl-mdr{color:var(--color-prettylights-syntax-meta-diff-range);font-weight:700}div#\:\$p > svg > foreignObject > section .pl-ba{color:var(--color-prettylights-syntax-brackethighlighter-angle)}div#\:\$p > svg > foreignObject > section .pl-sg{color:var(--color-prettylights-syntax-sublimelinter-gutter-mark)}div#\:\$p > svg > foreignObject > section .pl-corl{color:var(--color-prettylights-syntax-constant-other-reference-link);text-decoration:underline}div#\:\$p > svg > foreignObject > section [role=button]:focus:not(:focus-visible),div#\:\$p > svg > foreignObject > section [role=tabpanel][tabindex="0"]:focus:not(:focus-visible),div#\:\$p > svg > foreignObject > section a:focus:not(:focus-visible),div#\:\$p > svg > foreignObject > section button:focus:not(:focus-visible),div#\:\$p > svg > foreignObject > section summary:focus:not(:focus-visible){box-shadow:none;outline:none}div#\:\$p > svg > foreignObject > section [tabindex="0"]:focus:not(:focus-visible),div#\:\$p > svg > foreignObject > section details-dialog:focus:not(:focus-visible){outline:none}div#\:\$p > svg > foreignObject > section g-emoji{display:inline-block;font-family:Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;font-size:1em;font-style:normal!important;font-weight:var(--base-text-weight-normal, 400);line-height:1;min-width:1ch;vertical-align:-.075em}div#\:\$p > svg > foreignObject > section g-emoji img{height:1em;width:1em}div#\:\$p > svg > foreignObject > section .task-list-item{list-style-type:none}div#\:\$p > svg > foreignObject > section .task-list-item label{font-weight:var(--base-text-weight-normal, 400)}div#\:\$p > svg > foreignObject > section .task-list-item.enabled label{cursor:pointer}div#\:\$p > svg > foreignObject > section .task-list-item+.task-list-item{margin-top:var(--base-size-4)}div#\:\$p > svg > foreignObject > section .task-list-item .handle{display:none}div#\:\$p > svg > foreignObject > section .task-list-item-checkbox{margin:0 .2em .25em -1.4em;vertical-align:middle}div#\:\$p > svg > foreignObject > section ul:dir(rtl) .task-list-item-checkbox{margin:0 -1.6em .25em .2em}div#\:\$p > svg > foreignObject > section ol:dir(rtl) .task-list-item-checkbox{margin:0 -1.6em .25em .2em}div#\:\$p > svg > foreignObject > section .contains-task-list:focus-within .task-list-item-convert-container,div#\:\$p > svg > foreignObject > section .contains-task-list:hover .task-list-item-convert-container{display:block;height:24px;overflow:visible;width:auto;clip:auto}div#\:\$p > svg > foreignObject > section ::-webkit-calendar-picker-indicator{filter:invert(50%)}div#\:\$p > svg > foreignObject > section .markdown-alert{border-left:.25em solid var(--borderColor-default);color:inherit;margin-bottom:var(--base-size-16);padding:var(--base-size-8) var(--base-size-16)}div#\:\$p > svg > foreignObject > section .markdown-alert>:first-child{margin-top:0}div#\:\$p > svg > foreignObject > section .markdown-alert>:last-child{margin-bottom:0}div#\:\$p > svg > foreignObject > section .markdown-alert .markdown-alert-title{align-items:center;display:flex;font-weight:var(--base-text-weight-medium, 500);line-height:1}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-note{border-left-color:var(--borderColor-accent-emphasis)}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-note .markdown-alert-title{color:var(--fgColor-accent)}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-important{border-left-color:var(--borderColor-done-emphasis)}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-important .markdown-alert-title{color:var(--fgColor-done)}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-warning{border-left-color:var(--borderColor-attention-emphasis)}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-warning .markdown-alert-title{color:var(--fgColor-attention)}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-tip{border-left-color:var(--borderColor-success-emphasis)}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-tip .markdown-alert-title{color:var(--fgColor-success)}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-caution{border-left-color:var(--borderColor-danger-emphasis)}div#\:\$p > svg > foreignObject > section .markdown-alert.markdown-alert-caution .markdown-alert-title{color:var(--fgColor-danger)}div#\:\$p > svg > foreignObject > section>:first-child>.heading-element:first-child{margin-top:0!important}div#\:\$p > svg > foreignObject > section .highlight :is(pre, marp-pre):has(+.zeroclipboard-container){min-height:52px}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1){color:var(--h1-color);font-size:1.6em}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1),div#\:\$p > svg > foreignObject > section :is(h2, marp-h2){border-bottom:none}div#\:\$p > svg > foreignObject > section :is(h2, marp-h2){font-size:1.3em}div#\:\$p > svg > foreignObject > section :is(h3, marp-h3){font-size:1.1em}div#\:\$p > svg > foreignObject > section :is(h4, marp-h4){font-size:1.05em}div#\:\$p > svg > foreignObject > section :is(h5, marp-h5){font-size:1em}div#\:\$p > svg > foreignObject > section :is(h6, marp-h6){font-size:.9em}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1) strong,div#\:\$p > svg > foreignObject > section :is(h2, marp-h2) strong,div#\:\$p > svg > foreignObject > section :is(h3, marp-h3) strong,div#\:\$p > svg > foreignObject > section :is(h4, marp-h4) strong,div#\:\$p > svg > foreignObject > section :is(h5, marp-h5) strong,div#\:\$p > svg > foreignObject > section :is(h6, marp-h6) strong{color:var(--heading-strong-color);font-weight:inherit}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h2, marp-h2)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h3, marp-h3)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h4, marp-h4)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h5, marp-h5)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h6, marp-h6)::part(auto-scaling){max-height:563px}div#\:\$p > svg > foreignObject > section hr{height:0;padding-top:.25em}div#\:\$p > svg > foreignObject > section img{background-color:transparent}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre){border:1px solid var(--borderColor-default);line-height:1.15;overflow:visible}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre)::part(auto-scaling){max-height:529px}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs){color:var(--color-prettylights-syntax-storage-modifier-import)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-doctag),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-keyword),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-meta .hljs-keyword),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-template-tag),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-template-variable),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-type),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-variable.language_){color:var(--color-prettylights-syntax-keyword)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-title),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-title.class_),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-title.class_.inherited__),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-title.function_){color:var(--color-prettylights-syntax-entity)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-attr),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-attribute),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-literal),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-meta),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-number),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-operator),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-selector-attr),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-selector-class),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-selector-id),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-variable){color:var(--color-prettylights-syntax-constant)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-meta .hljs-string),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-regexp),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-string){color:var(--color-prettylights-syntax-string)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-built_in),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-symbol){color:var(--color-prettylights-syntax-variable)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-code),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-comment),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-formula){color:var(--color-prettylights-syntax-comment)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-name),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-quote),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-selector-pseudo),div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-selector-tag){color:var(--color-prettylights-syntax-entity-tag)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-subst){color:var(--color-prettylights-syntax-storage-modifier-import)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-section){color:var(--color-prettylights-syntax-markup-heading);font-weight:700}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-bullet){color:var(--color-prettylights-syntax-markup-list)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-emphasis){color:var(--color-prettylights-syntax-markup-italic);font-style:italic}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-strong){color:var(--color-prettylights-syntax-markup-bold);font-weight:700}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-addition){background-color:var(--color-prettylights-syntax-markup-inserted-bg);color:var(--color-prettylights-syntax-markup-inserted-text)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) :where(.hljs-deletion){background-color:var(--color-prettylights-syntax-markup-deleted-bg);color:var(--color-prettylights-syntax-markup-deleted-text)}div#\:\$p > svg > foreignObject > section footer,div#\:\$p > svg > foreignObject > section header{color:var(--header-footer-color);font-size:18px;left:30px;margin:0;position:absolute}div#\:\$p > svg > foreignObject > section header{top:21px}div#\:\$p > svg > foreignObject > section footer{bottom:21px}div#\:\$p > svg > foreignObject > section{--h1-color:#246;--header-footer-color:hsla(0,0%,40%,.75);--heading-strong-color:#48c;--paginate-color:#777;--base-size-4:4px;--base-size-8:8px;--base-size-16:16px;--base-size-24:24px;--base-size-40:40px;align-items:stretch;display:block;flex-flow:column nowrap;font-size:29px;height:720px;padding:78.5px;place-content:safe center center;width:1280px}div#\:\$p > svg > foreignObject > section{--marpit-root-font-size:29px;}div#\:\$p > svg > foreignObject > section:where(.invert){--h1-color:#cee7ff;--header-footer-color:hsla(0,0%,60%,.75);--heading-strong-color:#7bf;--paginate-color:#999;}div#\:\$p > svg > foreignObject > section>:last-child,div#\:\$p > svg > foreignObject > section[data-footer]>:nth-last-child(2){margin-bottom:0}div#\:\$p > svg > foreignObject > section>:first-child,div#\:\$p > svg > foreignObject > section>header:first-child+*{margin-top:0}div#\:\$p > svg > foreignObject > section:after{bottom:21px;color:var(--paginate-color);font-size:24px;padding:0;position:absolute;right:30px}div#\:\$p > svg > foreignObject > section:after{--marpit-root-font-size:24px;}div#\:\$p > svg > foreignObject > section[data-color] :is(h1, marp-h1),div#\:\$p > svg > foreignObject > section[data-color] :is(h2, marp-h2),div#\:\$p > svg > foreignObject > section[data-color] :is(h3, marp-h3),div#\:\$p > svg > foreignObject > section[data-color] :is(h4, marp-h4),div#\:\$p > svg > foreignObject > section[data-color] :is(h5, marp-h5),div#\:\$p > svg > foreignObject > section[data-color] :is(h6, marp-h6){color:currentcolor}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"]::before, div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"]::after, div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="content"]::before, div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="content"]::after{display:none!important}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction="vertical"]{flex-direction:column}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"][data-marpit-advanced-background-split] > div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split, 50%)}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"][data-marpit-advanced-background-split="right"] > div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container] > figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container] > figure > figcaption{position:absolute;border:0;clip:rect(0, 0, 0, 0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="content"], div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="pseudo"]{background:transparent!important}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="pseudo"], div#\:\$p > svg[data-marpit-svg] > foreignObject[data-marpit-advanced-background="pseudo"]{pointer-events:none!important}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background-split]{width:100%;height:100%}
|
11
|
+
</style></head><body><div class="bespoke-marp-osc"><button data-bespoke-marp-osc="prev" tabindex="-1" title="Previous slide">Previous slide</button><span data-bespoke-marp-osc="page"></span><button data-bespoke-marp-osc="next" tabindex="-1" title="Next slide">Next slide</button><button data-bespoke-marp-osc="fullscreen" tabindex="-1" title="Toggle fullscreen (f)">Toggle fullscreen</button><button data-bespoke-marp-osc="presenter" tabindex="-1" title="Open presenter view (p)">Open presenter view</button></div><div id=":$p"><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="1" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="1" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
12
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
13
|
+
|
14
|
+
<h1 id="%E8%B6%85%E5%85%A5%E9%96%80webassemblybr%E3%81%AE%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%92ruby%E3%81%A7%E6%9B%B8%E3%81%8F%E6%96%B9%E6%B3%95">超入門WebAssembly<br />(のランタイムをRubyで書く方法)</h1>
|
15
|
+
</section>
|
16
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="2" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="2" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
17
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
18
|
+
<h1 id="%E8%87%AA%E5%B7%B1%E7%B4%B9%E4%BB%8B">自己紹介</h1>
|
19
|
+
<ul>
|
20
|
+
<li>Uchio Kondo</li>
|
21
|
+
<li>@udzura</li>
|
22
|
+
</ul>
|
23
|
+
</section>
|
24
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="3" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="3" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
25
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
26
|
+
<h1 id="%E6%9C%80%E8%BF%91%E3%81%AE%E7%94%9F%E6%B4%BB">最近の生活</h1>
|
27
|
+
<ul>
|
28
|
+
<li>趣味: VM実装になりつつある...</li>
|
29
|
+
</ul>
|
30
|
+
</section>
|
31
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="4" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="4" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
32
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
33
|
+
<h1 id="mrubyedge">mruby/edge</h1>
|
34
|
+
<ul>
|
35
|
+
<li>Rustで書いたmrubyランタイム(mruby 3.x のバイトコードを実行可能)</li>
|
36
|
+
<li>基本的にmruby/cをベースにしている(一部必要な機能はmrubyから移植したい)</li>
|
37
|
+
</ul>
|
38
|
+
</section>
|
39
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="5" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="5" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
40
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
41
|
+
<h1 id="wardite">Wardite</h1>
|
42
|
+
<ul>
|
43
|
+
<li>Rubyで書いたWebAssemblyランタイム</li>
|
44
|
+
</ul>
|
45
|
+
</section>
|
46
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="6" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="6" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
47
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
48
|
+
<h1 id="%E4%BB%8A%E6%97%A5%E3%81%AF-wardite-%E3%81%AE%E8%A9%B1%E3%82%92%E3%81%97%E3%81%BE%E3%81%99">今日は Wardite の話をします</h1>
|
49
|
+
</section>
|
50
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="7" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="7" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
51
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
52
|
+
<h1 id="%E5%89%8D%E6%8F%90-webassembly-%E3%81%A8%E3%81%AF">前提: WebAssembly とは</h1>
|
53
|
+
</section>
|
54
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="8" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="8" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
55
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
56
|
+
<h1 id="webassembly-%E3%81%A8%E3%81%AF">WebAssembly とは</h1>
|
57
|
+
<ul>
|
58
|
+
<li>ブラウザで動くバイナリフォーマット</li>
|
59
|
+
<li>バイトコードをいろいろな言語(C, C++, Rust, ...)からコンパイルして、そのプログラムをブラウザの上で実行できる</li>
|
60
|
+
</ul>
|
61
|
+
</section>
|
62
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="9" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="9" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
63
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
64
|
+
<h1 id="webassembly-%E3%81%A8%E3%81%AF-1">WebAssembly とは</h1>
|
65
|
+
<ul>
|
66
|
+
<li><s>ブラウザで</s> いろいろなところで動くバイナリフォーマット</li>
|
67
|
+
</ul>
|
68
|
+
</section>
|
69
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="10" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="10" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
70
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
71
|
+
<h1 id="webassembly-%E3%81%AE%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88">WebAssembly のメリット</h1>
|
72
|
+
<ul>
|
73
|
+
<li>言語を選ばずにバイナリを作れる</li>
|
74
|
+
<li>そのバイナリは、ブラウザを中心にいろいろなところで動かせる
|
75
|
+
<ul>
|
76
|
+
<li>Write Once, Run Anywhere なのじゃよ...</li>
|
77
|
+
</ul>
|
78
|
+
</li>
|
79
|
+
<li>多くのランタイムで高速に動くことが期待できる
|
80
|
+
<ul>
|
81
|
+
<li>(安全性等もメリットですが今日は割愛)</li>
|
82
|
+
</ul>
|
83
|
+
</li>
|
84
|
+
</ul>
|
85
|
+
</section>
|
86
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="11" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="11" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
87
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
88
|
+
<h1 id="%E3%81%95%E3%81%A6wardite">さて、Wardite</h1>
|
89
|
+
</section>
|
90
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="12" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="12" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
91
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
92
|
+
<h1 id="wardite-%E3%81%AE%E7%89%B9%E5%BE%B4">Wardite の特徴</h1>
|
93
|
+
<ul>
|
94
|
+
<li>Pure Ruby 製
|
95
|
+
<ul>
|
96
|
+
<li>標準添付ライブラリ以外に動作上の依存ライブラリはなし</li>
|
97
|
+
</ul>
|
98
|
+
</li>
|
99
|
+
<li>Fully RBS annotated (rbs-inline)</li>
|
100
|
+
</ul>
|
101
|
+
</section>
|
102
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="13" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="13" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
103
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
104
|
+
<h1 id="%E3%81%AA%E3%81%9C-ruby-%E3%81%A7-webassembly-%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%92%E6%9B%B8%E3%81%8F%E3%81%AE%E3%81%8B">なぜ Ruby で WebAssembly ランタイムを書くのか</h1>
|
105
|
+
<ul>
|
106
|
+
<li>C拡張ベースの組み込みWebAssembly ランタイムなら実際結構ある
|
107
|
+
<ul>
|
108
|
+
<li>Wasmtime, Wasmedge, Wasmer, ...</li>
|
109
|
+
</ul>
|
110
|
+
</li>
|
111
|
+
<li>速度面でも強みはあるでしょう...</li>
|
112
|
+
</ul>
|
113
|
+
</section>
|
114
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="14" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="14" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
115
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
116
|
+
<h1 id="%E3%81%A7%E3%82%82">でも...</h1>
|
117
|
+
<ul>
|
118
|
+
<li>みなさん、このメッセージ好きですか?</li>
|
119
|
+
</ul>
|
120
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>Building native extensions. This could take a while...
|
121
|
+
</code></pre>
|
122
|
+
</section>
|
123
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="15" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="15" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
124
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
125
|
+
<h1 id="cf-wazero">cf. <a href="https://github.com/tetratelabs/wazero">wazero</a></h1>
|
126
|
+
<ul>
|
127
|
+
<li>Pure Go の WebAssembly ランタイム</li>
|
128
|
+
<li>cgo を避けたいGoのコミュニティで受け入れられている
|
129
|
+
<ul>
|
130
|
+
<li>wazero + tinygo でGoだけのプラグイン機構があったりする</li>
|
131
|
+
<li><a href="https://github.com/knqyf263/go-plugin">https://github.com/knqyf263/go-plugin</a></li>
|
132
|
+
</ul>
|
133
|
+
</li>
|
134
|
+
</ul>
|
135
|
+
</section>
|
136
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="16" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="16" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
137
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
138
|
+
<h1 id="pure-ruby%E3%81%A7%E3%81%82%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AE%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88">Pure Rubyであることのメリット</h1>
|
139
|
+
<ul>
|
140
|
+
<li>インストール・セットアップが簡単
|
141
|
+
<ul>
|
142
|
+
<li>Rubyが動けば動く、プラットフォームに依存しにくい</li>
|
143
|
+
</ul>
|
144
|
+
</li>
|
145
|
+
<li>さらに、Warditeを頑張って高速化することで色々貢献も出てきそう</li>
|
146
|
+
</ul>
|
147
|
+
<h2 id="%E3%81%A8%E3%81%AF%E3%81%84%E3%81%88">とはいえ</h2>
|
148
|
+
<ul>
|
149
|
+
<li>最初は「勉強目的」ではあった。思ったよりちゃんと動くので色んなユースケースを考えている</li>
|
150
|
+
</ul>
|
151
|
+
</section>
|
152
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="17" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="17" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
153
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
154
|
+
<h1 id="demo">demo</h1>
|
155
|
+
</section>
|
156
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="18" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="18" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
157
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
158
|
+
<h1 id="%E3%81%93%E3%81%86%E3%81%84%E3%81%86c%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%89%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99">こういうCのコードがあります</h1>
|
159
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-comment">/* fibonacci number in C */</span>
|
160
|
+
<span class="hljs-type">int</span> <span class="hljs-title function_">fib</span><span class="hljs-params">(<span class="hljs-type">int</span> n)</span> {
|
161
|
+
<span class="hljs-keyword">if</span> (n <= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> n;
|
162
|
+
<span class="hljs-keyword">return</span> fib(n - <span class="hljs-number">1</span>) + fib(n - <span class="hljs-number">2</span>);
|
163
|
+
}
|
164
|
+
</code></pre>
|
165
|
+
</section>
|
166
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="19" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="19" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
167
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
168
|
+
<h1 id="%E3%81%93%E3%82%8C%E3%82%92webassembly%E3%81%AB%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%82%87%E3%81%86">これをWebAssemblyにコンパイルしてみましょう</h1>
|
169
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>$ clang --target=wasm32 \
|
170
|
+
--no-standard-libraries \
|
171
|
+
-Wl,--export-all -Wl,--no-entry \
|
172
|
+
-o fib.wasm \
|
173
|
+
fib.c
|
174
|
+
</code></pre>
|
175
|
+
</section>
|
176
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="20" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="20" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
177
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
178
|
+
<h1 id="%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%A7%E5%8B%95%E3%81%8B%E3%81%99">ブラウザで動かす</h1>
|
179
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-html"><span class="hljs-meta"><!DOCTYPE <span class="hljs-keyword">html</span>></span>
|
180
|
+
<span class="hljs-tag"><<span class="hljs-name">html</span>></span>
|
181
|
+
<span class="hljs-tag"><<span class="hljs-name">head</span>></span>
|
182
|
+
<span class="hljs-tag"><<span class="hljs-name">script</span>></span><span class="language-javascript">
|
183
|
+
<span class="hljs-title class_">WebAssembly</span>.<span class="hljs-title function_">instantiateStreaming</span>(<span class="hljs-title function_">fetch</span>(<span class="hljs-string">'./fib.wasm'</span>))
|
184
|
+
.<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">obj</span> =></span> {
|
185
|
+
<span class="hljs-title function_">alert</span>(<span class="hljs-string">`fib(20) = <span class="hljs-subst">${obj.instance.<span class="hljs-built_in">exports</span>.fib(<span class="hljs-number">20</span>)}</span>`</span>);
|
186
|
+
});
|
187
|
+
</span><span class="hljs-tag"></<span class="hljs-name">script</span>></span>
|
188
|
+
<span class="hljs-tag"></<span class="hljs-name">head</span>></span>
|
189
|
+
<span class="hljs-tag"><<span class="hljs-name">body</span>></span>
|
190
|
+
<span class="hljs-tag"></<span class="hljs-name">body</span>></span>
|
191
|
+
<span class="hljs-tag"></<span class="hljs-name">html</span>></span>
|
192
|
+
</code></pre>
|
193
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>$ ruby -run -e httpd . -p 8000
|
194
|
+
</code></pre>
|
195
|
+
</section>
|
196
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="21" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="21" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
197
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
198
|
+
<p><img src="./image.png" alt="" style="width:800px;" /></p>
|
199
|
+
</section>
|
200
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="22" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="22" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
201
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
202
|
+
<h1 id="%E6%89%8B%E5%85%83%E3%81%A7%E5%8B%95%E4%BD%9C">手元で動作</h1>
|
203
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>$ wasmtime --invoke fib fib.wasm 20
|
204
|
+
warning: using `--invoke` with a function that takes arguments
|
205
|
+
is experimental and may break in the future
|
206
|
+
warning: using `--invoke` with a function that returns values
|
207
|
+
is experimental and may break in the future
|
208
|
+
6765
|
209
|
+
</code></pre>
|
210
|
+
</section>
|
211
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="23" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="23" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
212
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
213
|
+
<h1 id="%E3%81%9D%E3%81%97%E3%81%A6-wardite%E3%81%A7%E3%82%82%E5%8B%95%E4%BD%9C">そして... Warditeでも動作</h1>
|
214
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code>$ bundle exec wardite fib.wasm fib 20
|
215
|
+
return value: I32(6765)
|
216
|
+
</code></pre>
|
217
|
+
</section>
|
218
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="24" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="24" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
219
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
220
|
+
<h1 id="wardite-%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93">Wardite を支える技術</h1>
|
221
|
+
</section>
|
222
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="25" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="25" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
223
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
224
|
+
<h1 id="%E6%9C%80%E5%88%9D%E3%81%AE%E5%AE%9F%E8%A3%85">最初の実装</h1>
|
225
|
+
<ul>
|
226
|
+
<li>ゴリラさんの「<a href="https://zenn.dev/skanehira/books/writing-wasm-runtime-in-rust">RustでWasm Runtimeを実装する</a>」を参考に実装を開始した</li>
|
227
|
+
<li>元のコードがRustなので、強烈に型で守られたかったのと、RBS自体経験が浅いので勉強も兼ね、Full RBSを目指して移植していった</li>
|
228
|
+
</ul>
|
229
|
+
</section>
|
230
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="26" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="26" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
231
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
232
|
+
<h2 id="%E5%BD%93%E6%99%82%E3%81%AE%E3%83%A1%E3%83%A2%E3%82%92%E8%A6%8B%E3%81%AA%E3%81%8C%E3%82%89%E6%8C%AF%E3%82%8A%E8%BF%94%E3%82%8B%E3%81%A8">当時のメモを見ながら振り返ると</h2>
|
233
|
+
<ul>
|
234
|
+
<li>最初はとにかくデータ構造を把握しようとした
|
235
|
+
<ul>
|
236
|
+
<li><a href="https://zenn.dev/skanehira/books/writing-wasm-runtime-in-rust/viewer/04_wasm_binary_structure#wasm%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%81%AE%E5%85%A8%E4%BD%93%E5%83%8F">Wasmバイナリの全体像</a></li>
|
237
|
+
</ul>
|
238
|
+
</li>
|
239
|
+
<li>なぜかCの構造体で表現してるメモが...</li>
|
240
|
+
</ul>
|
241
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">SectionHeader</span> {</span>
|
242
|
+
u8 code;
|
243
|
+
u32LEB128 size; <span class="hljs-comment">//先頭2バイトを除いたセクションデータのバイト数</span>
|
244
|
+
<span class="hljs-class"><span class="hljs-keyword">union</span> {</span>
|
245
|
+
u32LEB128 nr_types;
|
246
|
+
u32LEB128 nr_functions;
|
247
|
+
u32LEB128 nr_memories; <span class="hljs-comment">// num memoriesはメモリの個数だが、</span>
|
248
|
+
<span class="hljs-comment">// version 1の仕様ではメモリは1モジュールに1つしか定義できないので、</span>
|
249
|
+
<span class="hljs-comment">// 実質的にこの値は1で固定される。</span>
|
250
|
+
u32LEB128 nr_data_segments;
|
251
|
+
u32LEB128 nr_imports;
|
252
|
+
u32LEB128 nr_exports;
|
253
|
+
}
|
254
|
+
}
|
255
|
+
</code></pre>
|
256
|
+
</section>
|
257
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="27" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="27" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
258
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
259
|
+
<h2 id="section-size%E3%81%AFleb1281%E3%81%A7%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89%E3%81%95%E3%82%8C%E3%81%9Fu32">> section sizeはLEB128[1]でエンコードされたu32</h2>
|
260
|
+
<ul>
|
261
|
+
<li>LEB128っち何??????</li>
|
262
|
+
<li>DWARFの中とかで使われている可変長の数値表現らしい...</li>
|
263
|
+
</ul>
|
264
|
+
</section>
|
265
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="28" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="28" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
266
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
267
|
+
<h2 id="ruby%E3%81%A7%E5%AE%9F%E8%A3%85%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%84%E3%81%91%E3%81%AA%E3%81%84%E3%81%AE%E3%81%A7">Rubyで実装しないといけないので...</h2>
|
268
|
+
<ul>
|
269
|
+
<li>元の記事はnomのなんやライブラリを使っていたが、おれは自分で書いた</li>
|
270
|
+
</ul>
|
271
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"><span class="hljs-keyword">def</span> <span class="hljs-title function_">to_i_by_uleb128</span>(<span class="hljs-params">bytes</span>)
|
272
|
+
dest = <span class="hljs-number">0</span>
|
273
|
+
bytes.each_with_index <span class="hljs-keyword">do</span> |<span class="hljs-params">b, level</span>|
|
274
|
+
upper, lower = (b >> <span class="hljs-number">7</span>), (b & (<span class="hljs-number">1</span> << <span class="hljs-number">7</span>) - <span class="hljs-number">1</span>)
|
275
|
+
dest |= lower << (<span class="hljs-number">7</span> * level)
|
276
|
+
<span class="hljs-keyword">if</span> upper == <span class="hljs-number">0</span>
|
277
|
+
<span class="hljs-keyword">return</span> dest
|
278
|
+
<span class="hljs-keyword">end</span>
|
279
|
+
<span class="hljs-keyword">end</span>
|
280
|
+
<span class="hljs-keyword">raise</span> <span class="hljs-string">"unreachable"</span>
|
281
|
+
<span class="hljs-keyword">end</span>
|
282
|
+
|
283
|
+
to_i_by_uleb128 <span class="hljs-string">"\xB9\x64"</span>.unpack(<span class="hljs-string">"C*"</span>)
|
284
|
+
<span class="hljs-comment"># => 12857</span>
|
285
|
+
</code></pre>
|
286
|
+
</section>
|
287
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="29" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="29" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
288
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
289
|
+
<h2 id="%E3%81%93%E3%81%AE%E8%BE%BA%E3%82%8A%E3%81%AE%E6%83%85%E5%A0%B1%E3%82%92%E3%82%82%E3%81%A8%E3%81%AB%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%83%91%E3%83%BC%E3%82%B5%E3%82%92%E6%9B%B8%E3%81%8F">この辺りの情報をもとにバイナリパーサを書く</h2>
|
290
|
+
<ul>
|
291
|
+
<li>StringIO/File どちらも取る想定</li>
|
292
|
+
<li>バイト列を一つ一つ読み取る感じの実装になっている</li>
|
293
|
+
</ul>
|
294
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"> <span class="hljs-comment"># <span class="hljs-doctag">@rbs</span> return: Integer</span>
|
295
|
+
<span class="hljs-keyword">def</span> <span class="hljs-title function_">self</span>.preamble
|
296
|
+
asm = <span class="hljs-variable">@buf</span>.read <span class="hljs-number">4</span>
|
297
|
+
<span class="hljs-keyword">raise</span> <span class="hljs-title class_">LoadError</span>, <span class="hljs-string">"buffer too short"</span> <span class="hljs-keyword">if</span> !asm
|
298
|
+
<span class="hljs-keyword">raise</span> <span class="hljs-title class_">LoadError</span>, <span class="hljs-string">"invalid preamble"</span> asm != <span class="hljs-string">"\u0000asm"</span>
|
299
|
+
vstr = <span class="hljs-variable">@buf</span>.read(<span class="hljs-number">4</span>)
|
300
|
+
version = vstr.to_enum(<span class="hljs-symbol">:chars</span>)
|
301
|
+
.with_index
|
302
|
+
.inject(<span class="hljs-number">0</span>) {|<span class="hljs-params">dest, (c, i)</span>| dest |<span class="hljs-params"> (c.ord << i*8) }
|
303
|
+
<span class="hljs-keyword">raise</span> LoadError, "unsupported ver: #{version}" <span class="hljs-keyword">if</span> version != 1
|
304
|
+
|
305
|
+
version
|
306
|
+
<span class="hljs-keyword">end</span> # ...
|
307
|
+
</span></code></pre>
|
308
|
+
</section>
|
309
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="30" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="30" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
310
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
311
|
+
<h2 id="%E5%91%BD%E4%BB%A4%E3%82%92%E6%8A%8A%E6%8F%A1%E3%81%99%E3%82%8B">命令を把握する</h2>
|
312
|
+
<ul>
|
313
|
+
<li><a href="https://www.w3.org/TR/wasm-core-1/#a7-index-of-instructions">Wasm SpecのIndex of Instructions</a></li>
|
314
|
+
<li>メモには「思ったより多くなかった」って書いてあるが、いや多いでしょ(190個ぐらい)</li>
|
315
|
+
</ul>
|
316
|
+
</section>
|
317
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="31" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="31" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
318
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
319
|
+
<h2 id="webassembly-opcodes-table-%E3%81%8C%E4%BE%BF%E5%88%A9"><a href="https://pengowray.github.io/wasm-ops/">WebAssembly Opcodes Table</a> が便利</h2>
|
320
|
+
<p><img src="./image-1.png" alt="" style="width:1000px;" /></p>
|
321
|
+
</section>
|
322
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="32" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="32" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
323
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
324
|
+
<h2 id="%E9%A0%91%E5%BC%B5%E3%81%A3%E3%81%A6%E3%81%84%E3%81%9F%E9%81%8E%E5%8E%BB%E3%81%AE%E8%87%AA%E5%88%86">頑張っていた過去の自分</h2>
|
325
|
+
<ul>
|
326
|
+
<li>楽しそうですね</li>
|
327
|
+
</ul>
|
328
|
+
<p><img src="./image-2.png" alt="" style="width:550px;" /></p>
|
329
|
+
</section>
|
330
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="33" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="33" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
331
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
332
|
+
<h2 id="vm%E5%91%A8%E3%82%8A%E3%81%AE%E5%AE%9F%E8%A3%85">VM周りの実装</h2>
|
333
|
+
<ul>
|
334
|
+
<li><a href="https://webassembly.github.io/spec/core/exec/runtime.html#">Runtime Structure</a> も見ながら</li>
|
335
|
+
<li>Runtimeは以下のデータ構造を保持している
|
336
|
+
<ul>
|
337
|
+
<li>Store と呼ばれるglobal stateを表現した構造体</li>
|
338
|
+
<li>3つのスタック
|
339
|
+
<ul>
|
340
|
+
<li>Call Stack</li>
|
341
|
+
<li>Value Stack</li>
|
342
|
+
<li>Label Stack</li>
|
343
|
+
</ul>
|
344
|
+
</li>
|
345
|
+
</ul>
|
346
|
+
</li>
|
347
|
+
</ul>
|
348
|
+
</section>
|
349
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="34" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="34" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
350
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
351
|
+
<h2 id="ruby-%E3%81%A7%E6%9B%B8%E3%81%91%E3%81%B0%E3%81%93%E3%81%86%E3%81%84%E3%81%86%E6%84%9F%E3%81%98">Ruby で書けばこういう感じ</h2>
|
352
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Store</span>
|
353
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:funcs</span> <span class="hljs-comment">#: Array[WasmFunction|ExternalFunction]</span>
|
354
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:modules</span> <span class="hljs-comment">#: Hash[Symbol, wasmModule]</span>
|
355
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:memories</span> <span class="hljs-comment">#: Array[Memory]</span>
|
356
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:globals</span> <span class="hljs-comment">#: Array[Global]</span>
|
357
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:tables</span> <span class="hljs-comment">#: Array[Table]</span>
|
358
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:elements</span> <span class="hljs-comment">#: Array[[Symbol, Integer, Array[Integer]]]</span>
|
359
|
+
<span class="hljs-comment">#...</span>
|
360
|
+
</code></pre>
|
361
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Runtime</span>
|
362
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:store</span> <span class="hljs-comment">#: Store</span>
|
363
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:stack</span> <span class="hljs-comment">#: Array[wasmValue]</span>
|
364
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:call_stack</span> <span class="hljs-comment">#: Array[Frame]</span>
|
365
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:labels</span> <span class="hljs-comment">#: Array[Label]</span>
|
366
|
+
<span class="hljs-comment">#...</span>
|
367
|
+
</code></pre>
|
368
|
+
<ul>
|
369
|
+
<li>実際にはもっとごちゃついた関係になってる。整理したい...</li>
|
370
|
+
</ul>
|
371
|
+
</section>
|
372
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="35" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="35" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
373
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
374
|
+
<h2 id="%E5%91%BD%E4%BB%A4%E3%81%AF%E3%83%91%E3%83%BC%E3%82%B9%E3%81%97%E3%81%A6%E3%81%93%E3%81%86%E3%81%84%E3%81%86%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AB">命令はパースしてこういうクラスに</h2>
|
375
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Op</span>
|
376
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:namespace</span> <span class="hljs-comment">#: Symbol -- :i32/:i64/...</span>
|
377
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:code</span> <span class="hljs-comment">#: Symbol</span>
|
378
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:operand</span> <span class="hljs-comment">#: Array[operandItem]</span>
|
379
|
+
<span class="hljs-built_in">attr_accessor</span> <span class="hljs-symbol">:meta</span> <span class="hljs-comment">#: Hash[Symbol, Integer]</span>
|
380
|
+
<span class="hljs-keyword">end</span>
|
381
|
+
</code></pre>
|
382
|
+
<h2 id="vm%E3%81%AE%E5%91%BD%E4%BB%A4%E5%AE%9F%E8%A1%8C%E9%83%A8%E5%88%86">VMの命令実行部分</h2>
|
383
|
+
<ul>
|
384
|
+
<li>フレームに現在実行しているコード自体とその位置の情報がある</li>
|
385
|
+
<li>それを上からやっていく</li>
|
386
|
+
</ul>
|
387
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"><span class="hljs-comment"># <span class="hljs-doctag">@rbs</span> return: void</span>
|
388
|
+
<span class="hljs-keyword">def</span> <span class="hljs-title function_">execute!</span>
|
389
|
+
loop <span class="hljs-keyword">do</span>
|
390
|
+
cur_frame = <span class="hljs-variable language_">self</span>.call_stack.last <span class="hljs-comment">#: Frame</span>
|
391
|
+
<span class="hljs-keyword">if</span> !cur_frame
|
392
|
+
<span class="hljs-keyword">break</span>
|
393
|
+
<span class="hljs-keyword">end</span>
|
394
|
+
cur_frame.pc += <span class="hljs-number">1</span>
|
395
|
+
insn = cur_frame.body[cur_frame.pc]
|
396
|
+
<span class="hljs-keyword">if</span> !insn
|
397
|
+
<span class="hljs-keyword">break</span>
|
398
|
+
<span class="hljs-keyword">end</span>
|
399
|
+
eval_insn(cur_frame, insn)
|
400
|
+
<span class="hljs-keyword">end</span>
|
401
|
+
<span class="hljs-keyword">end</span>
|
402
|
+
</code></pre>
|
403
|
+
</section>
|
404
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="36" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="36" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
405
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
406
|
+
<h2 id="vm%E5%90%8D%E7%89%A9%E3%81%A7%E3%81%A3%E3%81%8B%E3%81%84case%E6%96%87">VM名物でっかいcase文</h2>
|
407
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"><span class="hljs-comment"># <span class="hljs-doctag">@rbs</span> frame: Frame</span>
|
408
|
+
<span class="hljs-comment"># <span class="hljs-doctag">@rbs</span> insn: Op</span>
|
409
|
+
<span class="hljs-comment"># <span class="hljs-doctag">@rbs</span> return: void</span>
|
410
|
+
<span class="hljs-keyword">def</span> <span class="hljs-title function_">eval_insn</span>(<span class="hljs-params">frame, insn</span>)
|
411
|
+
<span class="hljs-comment"># unmached namespace...</span>
|
412
|
+
<span class="hljs-keyword">case</span> insn.code
|
413
|
+
<span class="hljs-keyword">when</span> <span class="hljs-symbol">:unreachable</span>
|
414
|
+
<span class="hljs-keyword">raise</span> <span class="hljs-title class_">Unreachable</span>, <span class="hljs-string">"unreachable op"</span>
|
415
|
+
<span class="hljs-keyword">when</span> <span class="hljs-symbol">:nop</span>
|
416
|
+
<span class="hljs-keyword">return</span>
|
417
|
+
<span class="hljs-keyword">when</span> <span class="hljs-symbol">:br</span>
|
418
|
+
level = insn.operand[<span class="hljs-number">0</span>]
|
419
|
+
pc = do_branch(frame.labels, stack, level)
|
420
|
+
frame.pc = pc
|
421
|
+
<span class="hljs-comment">#...</span>
|
422
|
+
</code></pre>
|
423
|
+
</section>
|
424
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="37" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="37" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
425
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
426
|
+
<h2 id="%E3%81%A8%E3%81%93%E3%82%8D%E3%81%A7">ところで</h2>
|
427
|
+
<ul>
|
428
|
+
<li>i32/i64,f32/f64で共通の処理が多い</li>
|
429
|
+
<li>Generatorでまとめて作るようにした</li>
|
430
|
+
</ul>
|
431
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"><span class="hljs-keyword">when</span> <span class="hljs-symbol">:i32_add</span>
|
432
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
433
|
+
<span class="hljs-keyword">if</span> !right.is_a?(<span class="hljs-variable constant_">I32</span>) |<span class="hljs-params"></span>| !left.is_a?(<span class="hljs-variable constant_">I32</span>)
|
434
|
+
<span class="hljs-keyword">raise</span> <span class="hljs-title class_">EvalError</span>, <span class="hljs-string">"maybe empty or invalid stack"</span>
|
435
|
+
<span class="hljs-keyword">end</span>
|
436
|
+
runtime.stack.push(<span class="hljs-variable constant_">I32</span>(left.value + right.value))
|
437
|
+
|
438
|
+
<span class="hljs-comment"># ...</span>
|
439
|
+
<span class="hljs-keyword">when</span> <span class="hljs-symbol">:i64_add</span>
|
440
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
441
|
+
<span class="hljs-keyword">if</span> !right.is_a?(<span class="hljs-variable constant_">I64</span>) |<span class="hljs-params"></span>| !left.is_a?(<span class="hljs-variable constant_">I64</span>)
|
442
|
+
<span class="hljs-keyword">raise</span> <span class="hljs-title class_">EvalError</span>, <span class="hljs-string">"maybe empty or invalid stack"</span>
|
443
|
+
<span class="hljs-keyword">end</span>
|
444
|
+
runtime.stack.push(<span class="hljs-variable constant_">I64</span>(left.value + right.value))
|
445
|
+
</code></pre>
|
446
|
+
</section>
|
447
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="38" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="38" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
448
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
449
|
+
<h2 id="%E3%81%93%E3%81%86%E3%81%84%E3%81%86dsl%E3%81%A7%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%9F">こういうDSLで生成するようにした</h2>
|
450
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby">task <span class="hljs-symbol">:generate</span> <span class="hljs-keyword">do</span>
|
451
|
+
<span class="hljs-title class_">GenAlu</span>.execute(libdir + <span class="hljs-string">"/wardite/alu_i32.generated.rb"</span>, <span class="hljs-symbol">prefix:</span> <span class="hljs-string">"i32"</span>, <span class="hljs-symbol">defined_ops:</span> [
|
452
|
+
<span class="hljs-symbol">:load</span>,
|
453
|
+
<span class="hljs-symbol">:load8_s</span>,
|
454
|
+
<span class="hljs-symbol">:load8_u</span>,
|
455
|
+
<span class="hljs-symbol">:load16_s</span>,
|
456
|
+
<span class="hljs-symbol">:load16_u</span>,
|
457
|
+
<span class="hljs-symbol">:store</span>,
|
458
|
+
<span class="hljs-symbol">:store8</span>,
|
459
|
+
<span class="hljs-symbol">:store16</span>,
|
460
|
+
<span class="hljs-symbol">:const</span>,
|
461
|
+
<span class="hljs-symbol">:eqz</span>,
|
462
|
+
<span class="hljs-symbol">:eq</span>,
|
463
|
+
<span class="hljs-symbol">:ne</span>,
|
464
|
+
<span class="hljs-symbol">:lts</span>,
|
465
|
+
<span class="hljs-comment"># ...</span>
|
466
|
+
<span class="hljs-symbol">:rotr</span>,
|
467
|
+
])
|
468
|
+
</code></pre>
|
469
|
+
<ul>
|
470
|
+
<li>あとは <code>rake generate</code></li>
|
471
|
+
</ul>
|
472
|
+
</section>
|
473
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="39" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="39" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
474
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
475
|
+
<h2 id="%E3%81%AA%E3%81%9C%E3%82%B3%E3%83%BC%E3%83%89%E7%94%9F%E6%88%90">なぜコード生成?</h2>
|
476
|
+
<ul>
|
477
|
+
<li>メタプログラミングはやめとこかと思った
|
478
|
+
<ul>
|
479
|
+
<li>命令はすごい数そのパスを通るので、パフォーマンス面の心配</li>
|
480
|
+
<li>RBS/rbs-inline と相性が悪そうな予感(杞憂かもだが)</li>
|
481
|
+
</ul>
|
482
|
+
</li>
|
483
|
+
</ul>
|
484
|
+
</section>
|
485
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="40" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="40" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
486
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
487
|
+
<h2 id="%E9%96%A2%E6%95%B0%E3%82%92%E5%91%BC%E3%81%B6%E3%81%A8%E3%81%8D%E3%81%AE%E5%91%BD%E4%BB%A4%E3%81%AE%E8%A7%A3%E8%AA%AC">関数を呼ぶときの命令の解説</h2>
|
488
|
+
<ul>
|
489
|
+
<li>関数インスタンスを取り出してフレームをプッシュする</li>
|
490
|
+
</ul>
|
491
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"><span class="hljs-keyword">when</span> <span class="hljs-symbol">:call</span>
|
492
|
+
idx = insn.operand[<span class="hljs-number">0</span>]
|
493
|
+
fn = <span class="hljs-variable language_">self</span>.instance.store.funcs[idx]
|
494
|
+
<span class="hljs-keyword">case</span> fn
|
495
|
+
<span class="hljs-keyword">when</span> <span class="hljs-title class_">WasmFunction</span>
|
496
|
+
push_frame(fn)
|
497
|
+
<span class="hljs-comment"># ... call external</span>
|
498
|
+
<span class="hljs-keyword">else</span>
|
499
|
+
<span class="hljs-keyword">raise</span> <span class="hljs-title class_">GenericError</span>, <span class="hljs-string">"got a non-function pointer"</span>
|
500
|
+
<span class="hljs-keyword">end</span>
|
501
|
+
</code></pre>
|
502
|
+
</section>
|
503
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="41" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="41" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
504
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
505
|
+
<h2 id="%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%82%92%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%99%E3%82%8B%E3%82%B3%E3%83%BC%E3%83%89">フレームをプッシュするコード</h2>
|
506
|
+
<ul>
|
507
|
+
<li>初期変数(引数+コードで使う変数)をフレームに積む</li>
|
508
|
+
<li>pcを -1 に初期化</li>
|
509
|
+
<li>フレームをコールスタックに積む</li>
|
510
|
+
</ul>
|
511
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"><span class="hljs-keyword">def</span> <span class="hljs-title function_">push_frame</span>(<span class="hljs-params">wasm_function</span>)
|
512
|
+
local_start = stack.size - wasm_function.callsig.size
|
513
|
+
locals = stack[local_start..]
|
514
|
+
<span class="hljs-variable language_">self</span>.stack = drained_stack(local_start)
|
515
|
+
locals.concat(wasm_function.default_locals)
|
516
|
+
|
517
|
+
arity = wasm_function.retsig.size
|
518
|
+
frame = <span class="hljs-title class_">Frame</span>.new(-<span class="hljs-number">1</span>, stack.size, wasm_function.body, arity, locals)
|
519
|
+
<span class="hljs-variable language_">self</span>.call_stack.push(frame)
|
520
|
+
<span class="hljs-keyword">end</span>
|
521
|
+
</code></pre>
|
522
|
+
</section>
|
523
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="42" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="42" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
524
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
525
|
+
<h2 id="return%E3%81%99%E3%82%8B%E6%99%82">returnする時</h2>
|
526
|
+
<ul>
|
527
|
+
<li>stackを巻き戻します</li>
|
528
|
+
</ul>
|
529
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"><span class="hljs-keyword">def</span> <span class="hljs-title function_">stack_unwind</span>(<span class="hljs-params">sp, arity</span>)
|
530
|
+
<span class="hljs-keyword">if</span> arity > <span class="hljs-number">0</span>
|
531
|
+
<span class="hljs-keyword">if</span> arity > <span class="hljs-number">1</span>
|
532
|
+
<span class="hljs-keyword">raise</span> <span class="hljs-symbol">:</span><span class="hljs-symbol">:NotImplementedError</span>, <span class="hljs-string">"return artiy >= 2 not yet supported ;;"</span>
|
533
|
+
<span class="hljs-keyword">end</span>
|
534
|
+
value = stack.pop
|
535
|
+
<span class="hljs-variable language_">self</span>.stack = stack[<span class="hljs-number">0</span>...sp]
|
536
|
+
stack.push value
|
537
|
+
<span class="hljs-keyword">else</span>
|
538
|
+
<span class="hljs-variable language_">self</span>.stack = stack[<span class="hljs-number">0</span>...sp]
|
539
|
+
<span class="hljs-keyword">end</span>
|
540
|
+
<span class="hljs-keyword">end</span>
|
541
|
+
</code></pre>
|
542
|
+
</section>
|
543
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="43" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="43" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
544
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
545
|
+
<h2 id="wasi-p1-%E5%91%A8%E3%82%8A">WASI (p1) 周り</h2>
|
546
|
+
<ul>
|
547
|
+
<li>ただのimport moduleなのでまずその仕組みを作る</li>
|
548
|
+
<li>あとはこういう関数を地道に実装するだけやで...</li>
|
549
|
+
</ul>
|
550
|
+
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-ruby"><span class="hljs-keyword">class</span> <span class="hljs-title class_">WasiSnapshotPreview1</span>
|
551
|
+
<span class="hljs-comment"># <span class="hljs-doctag">@rbs</span> store: Store</span>
|
552
|
+
<span class="hljs-comment"># <span class="hljs-doctag">@rbs</span> args: Array[wasmValue]</span>
|
553
|
+
<span class="hljs-comment"># <span class="hljs-doctag">@rbs</span> return: Object</span>
|
554
|
+
<span class="hljs-keyword">def</span> <span class="hljs-title function_">random_get</span>(<span class="hljs-params">store, args</span>)
|
555
|
+
buf = args[<span class="hljs-number">0</span>].value.to_i
|
556
|
+
buflen = args[<span class="hljs-number">1</span>].value.to_i
|
557
|
+
randoms = <span class="hljs-title class_">SecureRandom</span>.random_bytes(buflen) <span class="hljs-comment">#: String</span>
|
558
|
+
memory = store.memories[<span class="hljs-number">0</span>]
|
559
|
+
memory.data[buf...(buf+buflen)] = randoms
|
560
|
+
<span class="hljs-number">0</span>
|
561
|
+
<span class="hljs-keyword">end</span>
|
562
|
+
<span class="hljs-keyword">end</span>
|
563
|
+
</code></pre>
|
564
|
+
<ul>
|
565
|
+
<li>ちなみに、hello worldだけなら <code>fd_write</code> のみでいける</li>
|
566
|
+
</ul>
|
567
|
+
</section>
|
568
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="44" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="44" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
569
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
570
|
+
<h1 id="%E3%81%A8%E3%81%84%E3%81%86%E6%84%9F%E3%81%98%E3%81%A7%E5%9C%B0%E9%81%93%E3%81%AB%E5%AE%9F%E8%A3%85%E4%B8%AD">という感じで地道に実装中</h1>
|
571
|
+
</section>
|
572
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="45" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="45" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
573
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
574
|
+
<h1 id="%E4%BB%96%E8%A9%B1%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%93%E3%81%A8">他、話していないこと</h1>
|
575
|
+
<ul>
|
576
|
+
<li>WASM specに対応したテスト実行の仕方
|
577
|
+
<ul>
|
578
|
+
<li><a href="https://udzura.hatenablog.jp/entry/2024/11/24/210124">ブログに少し書いた</a></li>
|
579
|
+
<li>超カバレッジ低い、i32系だけ。</li>
|
580
|
+
</ul>
|
581
|
+
</li>
|
582
|
+
<li>パフォーマンスチューニング
|
583
|
+
<ul>
|
584
|
+
<li><a href="https://udzura.hatenablog.jp/entry/2024/12/20/173728">ブログ書いた</a></li>
|
585
|
+
</ul>
|
586
|
+
</li>
|
587
|
+
</ul>
|
588
|
+
</section>
|
589
|
+
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="46" data-class="lead" data-paginate="true" data-background-color="#fff" data-background-image="url('https://example.com/background.png')" data-header="超入門WebAssembly(のランタイムをRubyで書く方法)" data-theme="default" lang="ja-JP" class="lead" data-marpit-pagination="46" style="--class:lead;--paginate:true;--background-color:#fff;--background-image:url('https://example.com/background.png');--header:超入門WebAssembly(のランタイムをRubyで書く方法);--theme:default;background-color:#fff;background-image:url('https://example.com/background.png');background-position:center;background-repeat:no-repeat;background-size:cover;" data-marpit-pagination-total="46">
|
590
|
+
<header>超入門WebAssembly(のランタイムをRubyで書く方法)</header>
|
591
|
+
<h1 id="%E4%BB%8A%E5%BE%8C%E3%81%AE%E5%B1%95%E6%9C%9B">今後の展望</h1>
|
592
|
+
<ul>
|
593
|
+
<li>WASI、specカバレッジ、パフォチューを地道に</li>
|
594
|
+
<li><code>ruby.wasm</code> を動かしたいぞん
|
595
|
+
<ul>
|
596
|
+
<li>ひとまずWASIサポート関数を増やすなど頑張りが必要</li>
|
597
|
+
<li>速度は... 我慢で対応(?)</li>
|
598
|
+
</ul>
|
599
|
+
</li>
|
600
|
+
<li>Component も読めるようにしたい
|
601
|
+
<ul>
|
602
|
+
<li>簡単なものならまあ...</li>
|
603
|
+
</ul>
|
604
|
+
</li>
|
605
|
+
<li>もちろん、松山でWarditeの話をしたいですね
|
606
|
+
<ul>
|
607
|
+
<li>mruby/edgeか、どちらかをね。</li>
|
608
|
+
</ul>
|
609
|
+
</li>
|
610
|
+
</ul>
|
611
|
+
</section>
|
612
|
+
<script>!function(){"use strict";const t={h1:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"1"},style:"display: block; font-size: 2em; margin-block-start: 0.67em; margin-block-end: 0.67em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h2:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"2"},style:"display: block; font-size: 1.5em; margin-block-start: 0.83em; margin-block-end: 0.83em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h3:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"3"},style:"display: block; font-size: 1.17em; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h4:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"4"},style:"display: block; margin-block-start: 1.33em; margin-block-end: 1.33em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h5:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"5"},style:"display: block; font-size: 0.83em; margin-block-start: 1.67em; margin-block-end: 1.67em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h6:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"6"},style:"display: block; font-size: 0.67em; margin-block-start: 2.33em; margin-block-end: 2.33em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},span:{proto:()=>HTMLSpanElement},pre:{proto:()=>HTMLElement,style:"display: block; font-family: monospace; white-space: pre; margin: 1em 0; --marp-auto-scaling-white-space: pre;"}},e="data-marp-auto-scaling-wrapper",i="data-marp-auto-scaling-svg",n="data-marp-auto-scaling-container";class s extends HTMLElement{container;containerSize;containerObserver;svg;svgComputedStyle;svgPreserveAspectRatio="xMinYMid meet";wrapper;wrapperSize;wrapperObserver;constructor(){super();const t=t=>([e])=>{const{width:i,height:n}=e.contentRect;this[t]={width:i,height:n},this.updateSVGRect()};this.attachShadow({mode:"open"}),this.containerObserver=new ResizeObserver(t("containerSize")),this.wrapperObserver=new ResizeObserver(((...e)=>{t("wrapperSize")(...e),this.flushSvgDisplay()}))}static get observedAttributes(){return["data-downscale-only"]}connectedCallback(){this.shadowRoot.innerHTML=`\n<style>\n svg[${i}] { display: block; width: 100%; height: auto; vertical-align: top; }\n span[${n}] { display: table; white-space: var(--marp-auto-scaling-white-space, nowrap); width: max-content; }\n</style>\n<div ${e}>\n <svg part="svg" ${i}>\n <foreignObject><span ${n}><slot></slot></span></foreignObject>\n </svg>\n</div>\n `.split(/\n\s*/).join(""),this.wrapper=this.shadowRoot.querySelector(`div[${e}]`)??void 0;const t=this.svg;this.svg=this.wrapper?.querySelector(`svg[${i}]`)??void 0,this.svg!==t&&(this.svgComputedStyle=this.svg?window.getComputedStyle(this.svg):void 0),this.container=this.svg?.querySelector(`span[${n}]`)??void 0,this.observe()}disconnectedCallback(){this.svg=void 0,this.svgComputedStyle=void 0,this.wrapper=void 0,this.container=void 0,this.observe()}attributeChangedCallback(){this.observe()}flushSvgDisplay(){const{svg:t}=this;t&&(t.style.display="inline",requestAnimationFrame((()=>{t.style.display=""})))}observe(){this.containerObserver.disconnect(),this.wrapperObserver.disconnect(),this.wrapper&&this.wrapperObserver.observe(this.wrapper),this.container&&this.containerObserver.observe(this.container),this.svgComputedStyle&&this.observeSVGStyle(this.svgComputedStyle)}observeSVGStyle(t){const e=()=>{const i=(()=>{const e=t.getPropertyValue("--preserve-aspect-ratio");if(e)return e.trim();return`x${(({textAlign:t,direction:e})=>{if(t.endsWith("left"))return"Min";if(t.endsWith("right"))return"Max";if("start"===t||"end"===t){let i="rtl"===e;return"end"===t&&(i=!i),i?"Max":"Min"}return"Mid"})(t)}YMid meet`})();i!==this.svgPreserveAspectRatio&&(this.svgPreserveAspectRatio=i,this.updateSVGRect()),t===this.svgComputedStyle&&requestAnimationFrame(e)};e()}updateSVGRect(){let t=Math.ceil(this.containerSize?.width??0);const e=Math.ceil(this.containerSize?.height??0);void 0!==this.dataset.downscaleOnly&&(t=Math.max(t,this.wrapperSize?.width??0));const i=this.svg?.querySelector(":scope > foreignObject");if(i?.setAttribute("width",`${t}`),i?.setAttribute("height",`${e}`),this.svg&&(this.svg.setAttribute("viewBox",`0 0 ${t} ${e}`),this.svg.setAttribute("preserveAspectRatio",this.svgPreserveAspectRatio),this.svg.style.height=t<=0||e<=0?"0":""),this.container){const t=this.svgPreserveAspectRatio.toLowerCase();this.container.style.marginLeft=t.startsWith("xmid")||t.startsWith("xmax")?"auto":"0",this.container.style.marginRight=t.startsWith("xmi")?"auto":"0"}}}const r=(t,{attrs:e={},style:i})=>class extends t{constructor(...t){super(...t);for(const[t,i]of Object.entries(e))this.hasAttribute(t)||this.setAttribute(t,i);this._shadow()}static get observedAttributes(){return["data-auto-scaling"]}connectedCallback(){this._update()}attributeChangedCallback(){this._update()}_shadow(){if(!this.shadowRoot)try{this.attachShadow({mode:"open"})}catch(t){if(!(t instanceof Error&&"NotSupportedError"===t.name))throw t}return this.shadowRoot}_update(){const t=this._shadow();if(t){const e=i?`<style>:host { ${i} }</style>`:"";let n="<slot></slot>";const{autoScaling:s}=this.dataset;if(void 0!==s){n=`<marp-auto-scaling exportparts="svg:auto-scaling" ${"downscale-only"===s?"data-downscale-only":""}>${n}</marp-auto-scaling>`}t.innerHTML=e+n}}};let o;const a=Symbol();let l;const c="marpitSVGPolyfill:setZoomFactor,",d=Symbol(),h=Symbol();const g=()=>{const t="Apple Computer, Inc."===navigator.vendor,e=t?[u]:[],i={then:e=>(t?(async()=>{if(void 0===l){const t=document.createElement("canvas");t.width=10,t.height=10;const e=t.getContext("2d"),i=new Image(10,10),n=new Promise((t=>{i.addEventListener("load",(()=>t()))}));i.crossOrigin="anonymous",i.src="data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2210%22%20height%3D%2210%22%20viewBox%3D%220%200%201%201%22%3E%3CforeignObject%20width%3D%221%22%20height%3D%221%22%20requiredExtensions%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%3Cdiv%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%20style%3D%22width%3A%201px%3B%20height%3A%201px%3B%20background%3A%20red%3B%20position%3A%20relative%22%3E%3C%2Fdiv%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E",await n,e.drawImage(i,0,0),l=e.getImageData(5,5,1,1).data[3]<128}return l})().then((t=>{null==e||e(t?[u]:[])})):null==e||e([]),i)};return Object.assign(e,i)};let p,m;function u(t){const e="object"==typeof t&&t.target||document,i="object"==typeof t?t.zoom:t;window[h]||(Object.defineProperty(window,h,{configurable:!0,value:!0}),document.body.style.zoom=1.0001,document.body.offsetHeight,document.body.style.zoom=1,window.addEventListener("message",(({data:t,origin:e})=>{if(e===window.origin)try{if(t&&"string"==typeof t&&t.startsWith(c)){const[,e]=t.split(","),i=Number.parseFloat(e);Number.isNaN(i)||(m=i)}}catch(t){console.error(t)}})));let n=!1;Array.from(e.querySelectorAll("svg[data-marpit-svg]"),(t=>{var e,s,r,o;t.style.transform||(t.style.transform="translateZ(0)");const a=i||m||t.currentScale||1;p!==a&&(p=a,n=a);const l=t.getBoundingClientRect(),{length:c}=t.children;for(let i=0;i<c;i+=1){const n=t.children[i];if(n.getScreenCTM){const t=n.getScreenCTM();if(t){const i=null!==(s=null===(e=n.x)||void 0===e?void 0:e.baseVal.value)&&void 0!==s?s:0,c=null!==(o=null===(r=n.y)||void 0===r?void 0:r.baseVal.value)&&void 0!==o?o:0,d=n.children.length;for(let e=0;e<d;e+=1){const s=n.children[e];if("SECTION"===s.tagName){const{style:e}=s;e.transformOrigin||(e.transformOrigin=`${-i}px ${-c}px`),e.transform=`scale(${a}) matrix(${t.a}, ${t.b}, ${t.c}, ${t.d}, ${t.e-l.left}, ${t.f-l.top}) translateZ(0.0001px)`;break}}}}}})),!1!==n&&Array.from(e.querySelectorAll("iframe"),(({contentWindow:t})=>{null==t||t.postMessage(`${c}${n}`,"null"===window.origin?"*":window.origin)}))}function v({once:t=!1,target:e=document}={}){const i=function(t=document){if(t[d])return t[d];let e=!0;const i=()=>{e=!1,delete t[d]};Object.defineProperty(t,d,{configurable:!0,value:i});let n=[],s=!1;(async()=>{try{n=await g()}finally{s=!0}})();const r=()=>{for(const e of n)e({target:t});s&&0===n.length||e&&window.requestAnimationFrame(r)};return r(),i}(e);return t?(i(),()=>{}):i}p=1,m=void 0;const w=Symbol(),b=(e=document)=>{if("undefined"==typeof window)throw new Error("Marp Core's browser script is valid only in browser context.");if(((e=document)=>{const i=window[a];i||customElements.define("marp-auto-scaling",s);for(const n of Object.keys(t)){const s=`marp-${n}`,a=t[n].proto();(o??(o=!!document.createElement("div",{is:"marp-auto-scaling"}).outerHTML.startsWith("<div is"),o))&&a!==HTMLElement?i||customElements.define(s,r(a,{style:t[n].style}),{extends:n}):(i||customElements.define(s,r(HTMLElement,t[n])),e.querySelectorAll(`${n}[is="${s}"]`).forEach((t=>{t.outerHTML=t.outerHTML.replace(new RegExp(`^<${n}`,"i"),`<${s}`).replace(new RegExp(`</${n}>$`,"i"),`</${s}>`)})))}window[a]=!0})(e),e[w])return e[w];const i=v({target:e}),n=()=>{i(),delete e[w]},l=Object.assign(n,{cleanup:n,update:()=>b(e)});return Object.defineProperty(e,w,{configurable:!0,value:l}),l},y=document.currentScript;b(y?y.getRootNode():document)}();
|
613
|
+
</script></foreignObject></svg></div><div class="bespoke-marp-note" data-index="11" tabindex="0"><p>ちなみに標準添付ライブラリもstringioだけです。これも削っちゃおうかな?</p></div><div class="bespoke-marp-note" data-index="25" tabindex="0"><p>この発表本当にRubyのコードでないなw</p></div><div class="bespoke-marp-note" data-index="38" tabindex="0"><p>GoとRustを結構書いてきたので、別に生成すれば良くね?って自然な気持ちで思ったのが大きいかな...</p></div><script>/*!! License: https://unpkg.com/@marp-team/marp-cli@4.0.4/lib/bespoke.js.LICENSE.txt */
|
614
|
+
!function(){"use strict";function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var t,n,r=(n||(n=1,t={from:function(e,t){var n,r=1===(e.parent||e).nodeType?e.parent||e:document.querySelector(e.parent||e),o=[].filter.call("string"==typeof e.slides?r.querySelectorAll(e.slides):e.slides||r.children,(function(e){return"SCRIPT"!==e.nodeName})),a={},i=function(e,t){return(t=t||{}).index=o.indexOf(e),t.slide=e,t},s=function(e,t){a[e]=(a[e]||[]).filter((function(e){return e!==t}))},c=function(e,t){return(a[e]||[]).reduce((function(e,n){return e&&!1!==n(t)}),!0)},l=function(e,t){o[e]&&(n&&c("deactivate",i(n,t)),n=o[e],c("activate",i(n,t)))},d=function(e,t){var r=o.indexOf(n)+e;c(e>0?"next":"prev",i(n,t))&&l(r,t)},u={off:s,on:function(e,t){return(a[e]||(a[e]=[])).push(t),s.bind(null,e,t)},fire:c,slide:function(e,t){if(!arguments.length)return o.indexOf(n);c("slide",i(o[e],t))&&l(e,t)},next:d.bind(null,1),prev:d.bind(null,-1),parent:r,slides:o,destroy:function(e){c("destroy",i(n,e)),a={}}};return(t||[]).forEach((function(e){e(u)})),n||l(0),u}}),t),o=e(r);const a=document.body,i=(...e)=>history.replaceState(...e),s="",c="presenter",l="next",d=["",c,l],u="bespoke-marp-",f=`data-${u}`,m=(e,{protocol:t,host:n,pathname:r,hash:o}=location)=>{const a=e.toString();return`${t}//${n}${r}${a?"?":""}${a}${o}`},g=()=>a.dataset.bespokeView,p=e=>new URLSearchParams(location.search).get(e),v=(e,t={})=>{const n={location,setter:i,...t},r=new URLSearchParams(n.location.search);for(const t of Object.keys(e)){const n=e[t];"string"==typeof n?r.set(t,n):r.delete(t)}try{n.setter({...window.history.state??{}},"",m(r,n.location))}catch(e){console.error(e)}},h=(()=>{const e="bespoke-marp";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch{return!1}})(),y=e=>{try{return localStorage.getItem(e)}catch{return null}},b=(e,t)=>{try{return localStorage.setItem(e,t),!0}catch{return!1}},w=e=>{try{return localStorage.removeItem(e),!0}catch{return!1}},x=(e,t)=>{const n="aria-hidden";t?e.setAttribute(n,"true"):e.removeAttribute(n)},k=e=>{e.parent.classList.add(`${u}parent`),e.slides.forEach((e=>e.classList.add(`${u}slide`))),e.on("activate",(t=>{const n=`${u}active`,r=t.slide,o=r.classList,a=!o.contains(n);if(e.slides.forEach((e=>{e.classList.remove(n),x(e,!0)})),o.add(n),x(r,!1),a){const e=`${n}-ready`;o.add(e),document.body.clientHeight,o.remove(e)}}))},$=e=>{let t=0,n=0;Object.defineProperty(e,"fragments",{enumerable:!0,value:e.slides.map((e=>[null,...e.querySelectorAll("[data-marpit-fragment]")]))});const r=r=>void 0!==e.fragments[t][n+r],o=(r,o)=>{t=r,n=o,e.fragments.forEach(((e,t)=>{e.forEach(((e,n)=>{if(null==e)return;const a=t<r||t===r&&n<=o;e.setAttribute(`${f}fragment`,(a?"":"in")+"active");const i=`${f}current-fragment`;t===r&&n===o?e.setAttribute(i,"current"):e.removeAttribute(i)}))})),e.fragmentIndex=o;const a={slide:e.slides[r],index:r,fragments:e.fragments[r],fragmentIndex:o};e.fire("fragment",a)};e.on("next",(({fragment:a=!0})=>{if(a){if(r(1))return o(t,n+1),!1;const a=t+1;e.fragments[a]&&o(a,0)}else{const r=e.fragments[t].length;if(n+1<r)return o(t,r-1),!1;const a=e.fragments[t+1];a&&o(t+1,a.length-1)}})),e.on("prev",(({fragment:a=!0})=>{if(r(-1)&&a)return o(t,n-1),!1;const i=t-1;e.fragments[i]&&o(i,e.fragments[i].length-1)})),e.on("slide",(({index:t,fragment:n})=>{let r=0;if(void 0!==n){const o=e.fragments[t];if(o){const{length:e}=o;r=-1===n?e-1:Math.min(Math.max(n,0),e-1)}}o(t,r)})),o(0,0)},E=document,L=()=>!(!E.fullscreenEnabled&&!E.webkitFullscreenEnabled),S=()=>!(!E.fullscreenElement&&!E.webkitFullscreenElement),P=e=>{e.fullscreen=()=>{L()&&(async()=>{S()?(E.exitFullscreen||E.webkitExitFullscreen)?.call(E):((e=E.body)=>{(e.requestFullscreen||e.webkitRequestFullscreen)?.call(e)})()})()},document.addEventListener("keydown",(t=>{"f"!==t.key&&"F11"!==t.key||t.altKey||t.ctrlKey||t.metaKey||!L()||(e.fullscreen(),t.preventDefault())}))},_=`${u}inactive`,T=(e=2e3)=>({parent:t,fire:n})=>{const r=t.classList,o=e=>n(`marp-${e?"":"in"}active`);let a;const i=()=>{a&&clearTimeout(a),a=setTimeout((()=>{r.add(_),o()}),e),r.contains(_)&&(r.remove(_),o(!0))};for(const e of["mousedown","mousemove","touchend"])document.addEventListener(e,i);setTimeout(i,0)},I=["AUDIO","BUTTON","INPUT","SELECT","TEXTAREA","VIDEO"],M=e=>{e.parent.addEventListener("keydown",(e=>{if(!e.target)return;const t=e.target;(I.includes(t.nodeName)||"true"===t.contentEditable)&&e.stopPropagation()}))},O=e=>{window.addEventListener("load",(()=>{for(const t of e.slides){const e=t.querySelector("marp-auto-scaling, [data-auto-scaling], [data-marp-fitting]");t.setAttribute(`${f}load`,e?"":"hideable")}}))},A=({interval:e=250}={})=>t=>{document.addEventListener("keydown",(e=>{if(" "===e.key&&e.shiftKey)t.prev();else if("ArrowLeft"===e.key||"ArrowUp"===e.key||"PageUp"===e.key)t.prev({fragment:!e.shiftKey});else if(" "!==e.key||e.shiftKey)if("ArrowRight"===e.key||"ArrowDown"===e.key||"PageDown"===e.key)t.next({fragment:!e.shiftKey});else if("End"===e.key)t.slide(t.slides.length-1,{fragment:-1});else{if("Home"!==e.key)return;t.slide(0)}else t.next();e.preventDefault()}));let n,r,o=0;t.parent.addEventListener("wheel",(a=>{let i=!1;const s=(e,t)=>{e&&(i=i||((e,t)=>((e,t)=>{const n="X"===t?"Width":"Height";return e[`client${n}`]<e[`scroll${n}`]})(e,t)&&((e,t)=>{const{overflow:n}=e,r=e[`overflow${t}`];return"auto"===n||"scroll"===n||"auto"===r||"scroll"===r})(getComputedStyle(e),t))(e,t)),e?.parentElement&&s(e.parentElement,t)};if(0!==a.deltaX&&s(a.target,"X"),0!==a.deltaY&&s(a.target,"Y"),i)return;a.preventDefault();const c=Math.sqrt(a.deltaX**2+a.deltaY**2);if(void 0!==a.wheelDelta){if(void 0===a.webkitForce&&Math.abs(a.wheelDelta)<40)return;if(a.deltaMode===a.DOM_DELTA_PIXEL&&c<4)return}else if(a.deltaMode===a.DOM_DELTA_PIXEL&&c<12)return;r&&clearTimeout(r),r=setTimeout((()=>{n=0}),e);const l=Date.now()-o<e,d=c<=n;if(n=c,l||d)return;let u;(a.deltaX>0||a.deltaY>0)&&(u="next"),(a.deltaX<0||a.deltaY<0)&&(u="prev"),u&&(t[u](),o=Date.now())}))},C=(e=`.${u}osc`)=>{const t=document.querySelector(e);if(!t)return()=>{};const n=(e,n)=>{t.querySelectorAll(`[${f}osc=${JSON.stringify(e)}]`).forEach(n)};return L()||n("fullscreen",(e=>e.style.display="none")),h||n("presenter",(e=>{e.disabled=!0,e.title="Presenter view is disabled due to restricted localStorage."})),e=>{t.addEventListener("click",(t=>{if(t.target instanceof HTMLElement){const{bespokeMarpOsc:n}=t.target.dataset;n&&t.target.blur();const r={fragment:!t.shiftKey};"next"===n?e.next(r):"prev"===n?e.prev(r):"fullscreen"===n?e?.fullscreen():"presenter"===n&&e.openPresenterView()}})),e.parent.appendChild(t),e.on("activate",(({index:t})=>{n("page",(n=>n.textContent=`Page ${t+1} of ${e.slides.length}`))})),e.on("fragment",(({index:t,fragments:r,fragmentIndex:o})=>{n("prev",(e=>e.disabled=0===t&&0===o)),n("next",(n=>n.disabled=t===e.slides.length-1&&o===r.length-1))})),e.on("marp-active",(()=>x(t,!1))),e.on("marp-inactive",(()=>x(t,!0))),L()&&(e=>{for(const t of["","webkit"])E.addEventListener(t+"fullscreenchange",e)})((()=>n("fullscreen",(e=>e.classList.toggle("exit",L()&&S())))))}},D=e=>{window.addEventListener("message",(t=>{if(t.origin!==window.origin)return;const[n,r]=t.data.split(":");if("navigate"===n){const[t,n]=r.split(",");let o=Number.parseInt(t,10),a=Number.parseInt(n,10)+1;a>=e.fragments[o].length&&(o+=1,a=0),e.slide(o,{fragment:a})}}))};var N,B,q,K,j,F,V,U={exports:{}},X=(N||(N=1,U.exports=(B=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],q=function(e){return String(e).replace(/[&<>"']/g,(function(e){return"&"+K[e]+";"}))},K={"&":"amp","<":"lt",">":"gt",'"':"quot","'":"apos"},j="dangerouslySetInnerHTML",F={className:"class",htmlFor:"for"},V={},function(e,t){var n=[],r="";t=t||{};for(var o=arguments.length;o-- >2;)n.push(arguments[o]);if("function"==typeof e)return t.children=n.reverse(),e(t);if(e){if(r+="<"+e,t)for(var a in t)!1!==t[a]&&null!=t[a]&&a!==j&&(r+=" "+(F[a]?F[a]:q(a))+'="'+q(t[a])+'"');r+=">"}if(-1===B.indexOf(e)){if(t[j])r+=t[j].__html;else for(;n.length;){var i=n.pop();if(i)if(i.pop)for(var s=i.length;s--;)n.push(i[s]);else r+=!0===V[i]?i:q(i)}r+=e?"</"+e+">":""}return V[r]=!0,r})),U.exports),H=e(X);const R=({children:e})=>H(null,null,...e),W=`${u}presenter-`,J={container:`${W}container`,dragbar:`${W}dragbar-container`,next:`${W}next`,nextContainer:`${W}next-container`,noteContainer:`${W}note-container`,noteWrapper:`${W}note-wrapper`,noteButtons:`${W}note-buttons`,infoContainer:`${W}info-container`,infoPage:`${W}info-page`,infoPageText:`${W}info-page-text`,infoPagePrev:`${W}info-page-prev`,infoPageNext:`${W}info-page-next`,noteButtonsBigger:`${W}note-bigger`,noteButtonsSmaller:`${W}note-smaller`,infoTime:`${W}info-time`,infoTimer:`${W}info-timer`},Y=e=>{const{title:t}=document;document.title="[Presenter view]"+(t?` - ${t}`:"");const n={},r=e=>(n[e]=n[e]||document.querySelector(`.${e}`),n[e]);document.body.appendChild((e=>{const t=document.createElement("div");return t.className=J.container,t.appendChild(e),t.insertAdjacentHTML("beforeend",H(R,null,H("div",{class:J.nextContainer},H("iframe",{class:J.next,src:"?view=next"})),H("div",{class:J.dragbar}),H("div",{class:J.noteContainer},H("div",{class:J.noteWrapper}),H("div",{class:J.noteButtons},H("button",{class:J.noteButtonsSmaller,tabindex:"-1",title:"Smaller notes font size"},"Smaller notes font size"),H("button",{class:J.noteButtonsBigger,tabindex:"-1",title:"Bigger notes font size"},"Bigger notes font size"))),H("div",{class:J.infoContainer},H("div",{class:J.infoPage},H("button",{class:J.infoPagePrev,tabindex:"-1",title:"Previous"},"Previous"),H("span",{class:J.infoPageText}),H("button",{class:J.infoPageNext,tabindex:"-1",title:"Next"},"Next")),H("time",{class:J.infoTime,title:"Current time"}),H("time",{class:J.infoTimer,title:"Timer"})))),t})(e.parent)),(e=>{let t=!1;r(J.dragbar).addEventListener("mousedown",(()=>{t=!0,r(J.dragbar).classList.add("active")})),window.addEventListener("mouseup",(()=>{t=!1,r(J.dragbar).classList.remove("active")})),window.addEventListener("mousemove",(e=>{if(!t)return;const n=e.clientX/document.documentElement.clientWidth*100;r(J.container).style.setProperty("--bespoke-marp-presenter-split-ratio",`${Math.max(0,Math.min(100,n))}%`)})),r(J.nextContainer).addEventListener("click",(()=>e.next()));const n=r(J.next),o=(a=n,(e,t)=>a.contentWindow?.postMessage(`navigate:${e},${t}`,"null"===window.origin?"*":window.origin));var a;n.addEventListener("load",(()=>{r(J.nextContainer).classList.add("active"),o(e.slide(),e.fragmentIndex),e.on("fragment",(({index:e,fragmentIndex:t})=>o(e,t)))}));const i=document.querySelectorAll(".bespoke-marp-note");i.forEach((e=>{e.addEventListener("keydown",(e=>e.stopPropagation())),r(J.noteWrapper).appendChild(e)})),e.on("activate",(()=>i.forEach((t=>t.classList.toggle("active",t.dataset.index==e.slide())))));let s=0;const c=e=>{s=Math.max(-5,s+e),r(J.noteContainer).style.setProperty("--bespoke-marp-note-font-scale",(1.2**s).toFixed(4))},l=()=>c(1),d=()=>c(-1),u=r(J.noteButtonsBigger),f=r(J.noteButtonsSmaller);u.addEventListener("click",(()=>{u.blur(),l()})),f.addEventListener("click",(()=>{f.blur(),d()})),document.addEventListener("keydown",(e=>{"+"===e.key&&l(),"-"===e.key&&d()}),!0),e.on("activate",(({index:t})=>{r(J.infoPageText).textContent=`${t+1} / ${e.slides.length}`}));const m=r(J.infoPagePrev),g=r(J.infoPageNext);m.addEventListener("click",(t=>{m.blur(),e.prev({fragment:!t.shiftKey})})),g.addEventListener("click",(t=>{g.blur(),e.next({fragment:!t.shiftKey})})),e.on("fragment",(({index:t,fragments:n,fragmentIndex:r})=>{m.disabled=0===t&&0===r,g.disabled=t===e.slides.length-1&&r===n.length-1}));let p=new Date;const v=()=>{const e=new Date,t=e=>`${Math.floor(e)}`.padStart(2,"0"),n=e.getTime()-p.getTime(),o=t(n/1e3%60),a=t(n/1e3/60%60),i=t(n/36e5%24);r(J.infoTime).textContent=e.toLocaleTimeString(),r(J.infoTimer).textContent=`${i}:${a}:${o}`};v(),setInterval(v,250),r(J.infoTimer).addEventListener("click",(()=>{p=new Date}))})(e)},z=e=>{if(!(e=>e.syncKey&&"string"==typeof e.syncKey)(e))throw new Error("The current instance of Bespoke.js is invalid for Marp bespoke presenter plugin.");Object.defineProperties(e,{openPresenterView:{enumerable:!0,value:G},presenterUrl:{enumerable:!0,get:Q}}),h&&document.addEventListener("keydown",(t=>{"p"!==t.key||t.altKey||t.ctrlKey||t.metaKey||(t.preventDefault(),e.openPresenterView())}))};function G(){const{max:e,floor:t}=Math,n=e(t(.85*window.innerWidth),640),r=e(t(.85*window.innerHeight),360);return window.open(this.presenterUrl,W+this.syncKey,`width=${n},height=${r},menubar=no,toolbar=no`)}function Q(){const e=new URLSearchParams(location.search);return e.set("view","presenter"),e.set("sync",this.syncKey),m(e)}const Z=e=>{const t=g();return t===l&&e.appendChild(document.createElement("span")),{[s]:z,[c]:Y,[l]:D}[t]},ee=e=>{e.on("activate",(t=>{document.querySelectorAll(".bespoke-progress-parent > .bespoke-progress-bar").forEach((n=>{n.style.flexBasis=100*t.index/(e.slides.length-1)+"%"}))}))},te=e=>{const t=Number.parseInt(e,10);return Number.isNaN(t)?null:t},ne=(e={})=>{const t={history:!0,...e};return e=>{let n=!0;const r=e=>{const t=n;try{return n=!0,e()}finally{n=t}},o=(t={fragment:!0})=>{let n=t.fragment?te(p("f")||""):null;((t,n)=>{const{min:r,max:o}=Math,{fragments:a,slides:i}=e,s=o(0,r(t,i.length-1)),c=o(0,r(n||0,a[s].length-1));s===e.slide()&&c===e.fragmentIndex||e.slide(s,{fragment:c})})((()=>{if(location.hash){const[t]=location.hash.slice(1).split(":~:");if(/^\d+$/.test(t))return(te(t)??1)-1;const r=document.getElementById(t)||document.querySelector(`a[name="${CSS.escape(t)}"]`);if(r){const{length:t}=e.slides;for(let o=0;o<t;o+=1)if(e.slides[o].contains(r)){const t=e.fragments?.[o],a=r.closest("[data-marpit-fragment]");if(t&&a){const e=t.indexOf(a);e>=0&&(n=e)}return o}}}return 0})(),n)};e.on("fragment",(({index:e,fragmentIndex:r})=>{n||v({f:0===r||r.toString()},{location:{...location,hash:`#${e+1}`},setter:(...e)=>t.history?history.pushState(...e):history.replaceState(...e)})})),setTimeout((()=>{o(),window.addEventListener("hashchange",(()=>r((()=>{o({fragment:!1}),v({f:void 0})})))),window.addEventListener("popstate",(()=>{n||r((()=>o()))})),n=!1}),0)}},re=(e={})=>{const t=e.key||window.history.state?.marpBespokeSyncKey||Math.random().toString(36).slice(2),n=`bespoke-marp-sync-${t}`;var r;r={marpBespokeSyncKey:t},v({},{setter:(e,...t)=>i({...e,...r},...t)});const o=()=>{const e=y(n);return e?JSON.parse(e):Object.create(null)},a=e=>{const t=o(),r={...t,...e(t)};return b(n,JSON.stringify(r)),r},s=()=>{window.removeEventListener("pageshow",s),a((e=>({reference:(e.reference||0)+1})))};return e=>{s(),Object.defineProperty(e,"syncKey",{value:t,enumerable:!0});let r=!0;setTimeout((()=>{e.on("fragment",(e=>{r&&a((()=>({index:e.index,fragmentIndex:e.fragmentIndex})))}))}),0),window.addEventListener("storage",(t=>{if(t.key===n&&t.oldValue&&t.newValue){const n=JSON.parse(t.oldValue),o=JSON.parse(t.newValue);if(n.index!==o.index||n.fragmentIndex!==o.fragmentIndex)try{r=!1,e.slide(o.index,{fragment:o.fragmentIndex,forSync:!0})}finally{r=!0}}}));const i=()=>{const{reference:e}=o();void 0===e||e<=1?w(n):a((()=>({reference:e-1})))};window.addEventListener("pagehide",(e=>{e.persisted&&window.addEventListener("pageshow",s),i()})),e.on("destroy",i)}},{PI:oe,abs:ae,sqrt:ie,atan2:se}=Math,ce={passive:!0},le=({slope:e=-.7,swipeThreshold:t=30}={})=>n=>{let r;const o=n.parent,a=e=>{const t=o.getBoundingClientRect();return{x:e.pageX-(t.left+t.right)/2,y:e.pageY-(t.top+t.bottom)/2}};o.addEventListener("touchstart",(({touches:e})=>{r=1===e.length?a(e[0]):void 0}),ce),o.addEventListener("touchmove",(e=>{if(r)if(1===e.touches.length){e.preventDefault();const t=a(e.touches[0]),n=t.x-r.x,o=t.y-r.y;r.delta=ie(ae(n)**2+ae(o)**2),r.radian=se(n,o)}else r=void 0})),o.addEventListener("touchend",(o=>{if(r){if(r.delta&&r.delta>=t&&r.radian){const t=(r.radian-e+oe)%(2*oe)-oe;n[t<0?"next":"prev"](),o.stopPropagation()}r=void 0}}),ce)},de=new Map;de.clear(),de.set("none",{backward:{both:void 0,incoming:void 0,outgoing:void 0},forward:{both:void 0,incoming:void 0,outgoing:void 0}});const ue={both:"",outgoing:"outgoing-",incoming:"incoming-"},fe={forward:"",backward:"-backward"},me=e=>`--marp-bespoke-transition-animation-${e}`,ge=e=>`--marp-transition-${e}`,pe=me("name"),ve=me("duration"),he=e=>new Promise((t=>{const n={},r=document.createElement("div"),o=e=>{r.remove(),t(e)};r.addEventListener("animationstart",(()=>o(n))),Object.assign(r.style,{animationName:e,animationDuration:"1s",animationFillMode:"both",animationPlayState:"paused",position:"absolute",pointerEvents:"none"}),document.body.appendChild(r);const a=getComputedStyle(r).getPropertyValue(ge("duration"));a&&(n.defaultDuration=a),((e,t)=>{requestAnimationFrame((()=>{e.style.animationPlayState="running",requestAnimationFrame((()=>t(void 0)))}))})(r,o)})),ye=async e=>de.has(e)?de.get(e):(e=>{const t={},n=[];for(const[r,o]of Object.entries(ue))for(const[a,i]of Object.entries(fe)){const s=`marp-${o}transition${i}-${e}`;n.push(he(s).then((e=>{t[a]=t[a]||{},t[a][r]=e?{...e,name:s}:void 0})))}return Promise.all(n).then((()=>t))})(e).then((t=>(de.set(e,t),t))),be=e=>Object.values(e).flatMap(Object.values).every((e=>!e)),we=(e,{type:t,backward:n})=>{const r=e[n?"backward":"forward"],o=(()=>{const e=r[t],n=e=>({[pe]:e.name});if(e)return n(e);if(r.both){const e=n(r.both);return"incoming"===t&&(e[me("direction")]="reverse"),e}})();return!o&&n?we(e,{type:t,backward:!1}):o||{[pe]:"__bespoke_marp_transition_no_animation__"}},xe=e=>{if(e)try{const t=JSON.parse(e);if((e=>{if("object"!=typeof e)return!1;const t=e;return"string"==typeof t.name&&(void 0===t.duration||"string"==typeof t.duration)})(t))return t}catch{}},ke="_tSId",$e="_tA",Ee="bespoke-marp-transition-warming-up",Le=window.matchMedia("(prefers-reduced-motion: reduce)"),Se="__bespoke_marp_transition_reduced_outgoing__",Pe="__bespoke_marp_transition_reduced_incoming__",_e={forward:{both:void 0,incoming:{name:Pe},outgoing:{name:Se}},backward:{both:void 0,incoming:{name:Pe},outgoing:{name:Se}}},Te=e=>{if(!document.startViewTransition)return;const t=t=>(void 0!==t&&(e._tD=t),e._tD);let n;t(!1),((...e)=>{const t=[...new Set(e).values()];return Promise.all(t.map((e=>ye(e)))).then()})(...Array.from(document.querySelectorAll("section[data-transition], section[data-transition-back]")).flatMap((e=>[e.dataset.transition,e.dataset.transitionBack].flatMap((e=>{const t=xe(e);return[t?.name,t?.builtinFallback?`__builtin__${t.name}`:void 0]})).filter((e=>!!e))))).then((()=>{document.querySelectorAll("style").forEach((e=>{e.innerHTML=e.innerHTML.replace(/--marp-transition-duration:[^;}]*[;}]/g,(e=>e.slice(0,-1)+"!important"+e.slice(-1)))}))}));const r=(n,{back:r,cond:o})=>a=>{const i=t();if(i)return!!a[$e]||!("object"!=typeof i||(i.skipTransition(),!a.forSync));if(!o(a))return!0;const s=e.slides[e.slide()],c=()=>a.back??r,l="data-transition"+(c()?"-back":""),d=s.querySelector(`section[${l}]`);if(!d)return!0;const u=xe(d.getAttribute(l)??void 0);return!u||((async(e,{builtinFallback:t=!0}={})=>{let n=await ye(e);if(be(n)){if(!t)return;return n=await ye(`__builtin__${e}`),be(n)?void 0:n}return n})(u.name,{builtinFallback:u.builtinFallback}).then((e=>{if(!e){t(!0);try{n(a)}finally{t(!1)}return}let r=e;Le.matches&&(console.warn("Use a constant animation to transition because preferring reduced motion by viewer has detected."),r=_e);const o=document.getElementById(ke);o&&o.remove();const i=document.createElement("style");i.id=ke,document.head.appendChild(i),((e,t)=>{const n=[`:root{${ge("direction")}:${t.backward?-1:1};}`,":root:has(.bespoke-marp-inactive){cursor:none;}"],r=t=>{const n=e[t].both?.defaultDuration||e[t].outgoing?.defaultDuration||e[t].incoming?.defaultDuration;return"forward"===t?n:n||r("forward")},o=t.duration||r(t.backward?"backward":"forward");void 0!==o&&n.push(`::view-transition-group(*){${ve}:${o};}`);const a=e=>Object.entries(e).map((([e,t])=>`${e}:${t};`)).join("");return n.push(`::view-transition-old(root){${a(we(e,{...t,type:"outgoing"}))}}`,`::view-transition-new(root){${a(we(e,{...t,type:"incoming"}))}}`),n})(r,{backward:c(),duration:u.duration}).forEach((e=>i.sheet?.insertRule(e)));const s=document.documentElement.classList;s.add(Ee);let l=!1;const d=()=>{l||(n(a),l=!0,s.remove(Ee))},f=()=>{t(!1),i.remove(),s.remove(Ee)};try{t(!0);const e=document.startViewTransition(d);t(e),e.finished.finally(f)}catch(e){console.error(e),d(),f()}})),!1)};e.on("prev",r((t=>e.prev({...t,[$e]:!0})),{back:!0,cond:e=>e.index>0&&!((e.fragment??1)&&n.fragmentIndex>0)})),e.on("next",r((t=>e.next({...t,[$e]:!0})),{cond:t=>t.index+1<e.slides.length&&!(n.fragmentIndex+1<n.fragments.length)})),setTimeout((()=>{e.on("slide",r((t=>e.slide(t.index,{...t,[$e]:!0})),{cond:t=>{const n=e.slide();return t.index!==n&&(t.back=t.index<n,!0)}}))}),0),e.on("fragment",(e=>{n=e}))};let Ie;const Me=()=>(void 0===Ie&&(Ie="wakeLock"in navigator&&navigator.wakeLock),Ie),Oe=async()=>{const e=Me();if(e)try{return await e.request("screen")}catch(e){console.warn(e)}return null},Ae=async()=>{if(!Me())return;let e;const t=()=>{e&&"visible"===document.visibilityState&&Oe()};for(const e of["visibilitychange","fullscreenchange"])document.addEventListener(e,t);return e=await Oe(),e};((e=document.getElementById(":$p"))=>{(()=>{const e=p("view");a.dataset.bespokeView=e===l||e===c?e:""})();const t=(e=>{const t=p(e);return v({[e]:void 0}),t})("sync")||void 0;o.from(e,((...e)=>{const t=d.findIndex((e=>g()===e));return e.map((([e,n])=>e[t]&&n)).filter((e=>e))})([[1,1,0],re({key:t})],[[1,1,1],Z(e)],[[1,1,0],M],[[1,1,1],k],[[1,0,0],T()],[[1,1,1],O],[[1,1,1],ne({history:!1})],[[1,1,0],A()],[[1,1,0],P],[[1,0,0],ee],[[1,1,0],le()],[[1,0,0],C()],[[1,0,0],Te],[[1,1,1],$],[[1,1,0],Ae]))})()}();</script></body></html>
|