[{"data":1,"prerenderedAt":451},["ShallowReactive",2],{"msfe-doc:\u002Fen\u002Fextensions\u002Fresources":3},{"id":4,"title":5,"body":6,"description":436,"extension":437,"keywords":438,"locale":443,"meta":444,"navigation":445,"order":288,"path":446,"section":447,"seo":448,"stem":449,"__hash__":450},"docs\u002Fextensions\u002Fresources.en.md","Asynchronous resources and cleanup",{"type":7,"value":8,"toc":428},"minimark",[9,14,91,99,103,338,348,354,358,376,384,388,391,399,403,410,417,421,424],[10,11,13],"h2",{"id":12},"choose-the-shortest-correct-lifetime","Choose the shortest correct lifetime",[15,16,17,33],"table",{},[18,19,20],"thead",{},[21,22,23,27,30],"tr",{},[24,25,26],"th",{},"Scope",[24,28,29],{},"Ends when",[24,31,32],{},"Suitable resources",[34,35,36,51,64,78],"tbody",{},[21,37,38,45,48],{},[39,40,41],"td",{},[42,43,44],"code",{},"editor.scope",[39,46,47],{},"Editor disposal",[39,49,50],{},"Instance services and listeners",[21,52,53,58,61],{},[39,54,55],{},[42,56,57],{},"editor.documentScope",[39,59,60],{},"Document replacement or disposal",[39,62,63],{},"Saving, uploads and file queries",[21,65,66,72,75],{},[39,67,68,69],{},"ComponentView ",[42,70,71],{},"mount.scope",[39,73,74],{},"View unmount or replacement",[39,76,77],{},"Charts, previews and observers",[21,79,80,85,88],{},[39,81,82],{},[42,83,84],{},"scope.fork()",[39,86,87],{},"Cancellation or parent disposal",[39,89,90],{},"One request for one input generation",[92,93,94,95,98],"p",{},"Reusing a document ID does not reuse its lifetime. ",[42,96,97],{},"replaceDocument()"," ends the previous document scope. Observe that signal instead of comparing file names alone.",[10,100,102],{"id":101},"resource-leases","Resource leases",[104,105,110],"pre",{"className":106,"code":107,"language":108,"meta":109,"style":109},"language-ts shiki shiki-themes github-light github-light github-dark","const request = editor.documentScope.acquire(\n  async signal => {\n    const response = await fetch('\u002Fapi\u002Fpreview', { signal })\n    if (!response.ok) throw new Error(`HTTP ${response.status}`)\n    const url = URL.createObjectURL(await response.blob())\n    return { value: url, release: () => URL.revokeObjectURL(url) }\n  },\n  url => { console.log('Ready preview URL', url) },\n)\n\u002F\u002F The host may cancel this request before replacing the document.\nrequest.dispose()\n","ts","",[42,111,112,139,155,182,226,258,286,292,314,319,326],{"__ignoreMap":109},[113,114,117,121,125,128,132,136],"span",{"class":115,"line":116},"line",1,[113,118,120],{"class":119},"sDD9d","const",[113,122,124],{"class":123},"sUNQB"," request",[113,126,127],{"class":119}," =",[113,129,131],{"class":130},"sVPnS"," editor.documentScope.",[113,133,135],{"class":134},"sgQzM","acquire",[113,137,138],{"class":130},"(\n",[113,140,142,145,149,152],{"class":115,"line":141},2,[113,143,144],{"class":119},"  async",[113,146,148],{"class":147},"sde8i"," signal",[113,150,151],{"class":119}," =>",[113,153,154],{"class":130}," {\n",[113,156,158,161,164,166,169,172,175,179],{"class":115,"line":157},3,[113,159,160],{"class":119},"    const",[113,162,163],{"class":123}," response",[113,165,127],{"class":119},[113,167,168],{"class":119}," await",[113,170,171],{"class":134}," fetch",[113,173,174],{"class":130},"(",[113,176,178],{"class":177},"s-HEn","'\u002Fapi\u002Fpreview'",[113,180,181],{"class":130},", { signal })\n",[113,183,185,188,191,194,197,200,203,206,208,211,214,217,220,223],{"class":115,"line":184},4,[113,186,187],{"class":119},"    if",[113,189,190],{"class":130}," (",[113,192,193],{"class":119},"!",[113,195,196],{"class":130},"response.ok) ",[113,198,199],{"class":119},"throw",[113,201,202],{"class":119}," new",[113,204,205],{"class":134}," Error",[113,207,174],{"class":130},[113,209,210],{"class":177},"`HTTP ${",[113,212,213],{"class":130},"response",[113,215,216],{"class":177},".",[113,218,219],{"class":130},"status",[113,221,222],{"class":177},"}`",[113,224,225],{"class":130},")\n",[113,227,229,231,234,236,239,241,244,246,249,252,255],{"class":115,"line":228},5,[113,230,160],{"class":119},[113,232,233],{"class":123}," url",[113,235,127],{"class":119},[113,237,238],{"class":123}," URL",[113,240,216],{"class":130},[113,242,243],{"class":134},"createObjectURL",[113,245,174],{"class":130},[113,247,248],{"class":119},"await",[113,250,251],{"class":130}," response.",[113,253,254],{"class":134},"blob",[113,256,257],{"class":130},"())\n",[113,259,261,264,267,270,273,276,278,280,283],{"class":115,"line":260},6,[113,262,263],{"class":119},"    return",[113,265,266],{"class":130}," { value: url, ",[113,268,269],{"class":134},"release",[113,271,272],{"class":130},": () ",[113,274,275],{"class":119},"=>",[113,277,238],{"class":123},[113,279,216],{"class":130},[113,281,282],{"class":134},"revokeObjectURL",[113,284,285],{"class":130},"(url) }\n",[113,287,289],{"class":115,"line":288},7,[113,290,291],{"class":130},"  },\n",[113,293,295,298,300,303,306,308,311],{"class":115,"line":294},8,[113,296,297],{"class":147},"  url",[113,299,151],{"class":119},[113,301,302],{"class":130}," { console.",[113,304,305],{"class":134},"log",[113,307,174],{"class":130},[113,309,310],{"class":177},"'Ready preview URL'",[113,312,313],{"class":130},", url) },\n",[113,315,317],{"class":115,"line":316},9,[113,318,225],{"class":130},[113,320,322],{"class":115,"line":321},10,[113,323,325],{"class":324},"sqmzS","\u002F\u002F The host may cancel this request before replacing the document.\n",[113,327,329,332,335],{"class":115,"line":328},11,[113,330,331],{"class":130},"request.",[113,333,334],{"class":134},"dispose",[113,336,337],{"class":130},"()\n",[92,339,340,341,344,345,347],{},"The host implements ",[42,342,343],{},"\u002Fapi\u002Fpreview","; MSFE does not supply this service. ",[42,346,135],{}," delivers results only to current requests and releases leases arriving after cancellation. Each acquisition owns its lease. Do not let several views independently dispose the same shared object.",[92,349,350,353],{},[42,351,352],{},"scope.own(cleanup)"," registers idempotent cleanup and returns an early-release function. Disposal aborts first, then releases in reverse order. Uncancelable engines still need a signal check before accepting results and cleanup of obsolete results.",[10,355,357],{"id":356},"sourcedefinitionload","SourceDefinition.load",[92,359,360,361,364,365,368,369,371,372,375],{},"For attribute-bound resources, ",[42,362,363],{},"defineSource\u003CAttrs, Resource>({ load(attrs, signal) })"," returns ",[42,366,367],{},"{ value, release? }",". NodeViews read ",[42,370,219],{}," and ",[42,373,374],{},"resource","; they should not issue duplicate requests.",[92,377,378,379,216],{},"Attributes persist business identifiers. Resource values may contain resolved URLs, readonly display data or layout results. Never persist credentials or temporary object URLs in Markdown. See ",[380,381,383],"a",{"href":382},"\u002Fen\u002Fcustomization\u002Fimages","Images and external resources",[10,385,387],{"id":386},"errors-and-retry-belong-to-ui","Errors and retry belong to UI",[92,389,390],{},"An error report does not automatically render an error state. The component owns loading, ready and error UI, readable source fallback and retry. Each retry ends the previous child scope first.",[92,392,393,394,398],{},"If initialization throws after allocation but before returning its lease, release partial resources too. Register cleanup immediately or use try\u002Ffinally. The ",[380,395,397],{"href":396},"\u002Fen\u002Fextensions\u002Fdiagrams","chart renderer"," includes observer and instance ownership.",[10,400,402],{"id":401},"writing-after-asynchronous-completion","Writing after asynchronous completion",[92,404,405,406,216],{},"A live request does not imply a valid original source position. After upload, never insert using cached numeric offsets alone. Capture an anchor in a document child scope, get a fresh target on completion, then execute a command. See ",[380,407,409],{"href":408},"\u002Fen\u002Fguide\u002Fselection","the complete intent helper",[92,411,412,413,216],{},"Saving does not require replacing text with server responses. For serialized writes, retry and navigation flush, see ",[380,414,416],{"href":415},"\u002Fen\u002Fguide\u002Fsaving","Reading and saving",[10,418,420],{"id":419},"cleanup-tests","Cleanup tests",[92,422,423],{},"Use manually controlled promises: start A then B and complete A last; finish work after disposal; replace a document with the same ID; throw halfway through initialization. Assert no stale UI or writes, duplicate finalization or remaining observers.",[425,426,427],"style",{},"html pre.shiki code .sDD9d, html code.shiki .sDD9d{--shiki-default:#D73A49;--shiki-light:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sUNQB, html code.shiki .sUNQB{--shiki-default:#005CC5;--shiki-light:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVPnS, html code.shiki .sVPnS{--shiki-default:#24292E;--shiki-light:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sgQzM, html code.shiki .sgQzM{--shiki-default:#6F42C1;--shiki-light:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sde8i, html code.shiki .sde8i{--shiki-default:#E36209;--shiki-light:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s-HEn, html code.shiki .s-HEn{--shiki-default:#032F62;--shiki-light:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sqmzS, html code.shiki .sqmzS{--shiki-default:#6A737D;--shiki-light:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":109,"searchDepth":141,"depth":141,"links":429},[430,431,432,433,434,435],{"id":12,"depth":141,"text":13},{"id":101,"depth":141,"text":102},{"id":356,"depth":141,"text":357},{"id":386,"depth":141,"text":387},{"id":401,"depth":141,"text":402},{"id":419,"depth":141,"text":420},"Own loading, cancellation, retries and source intent across changing lifetimes.","md",[439,440,441,442,334],"TaskScope","ResourceLease","AbortSignal","load","en",{},true,"\u002Fen\u002Fextensions\u002Fresources","Extensions",{"title":5,"description":436},"extensions\u002Fresources.en","z4C8FVI9scwrRDBpmDFhZpPisZAum8Oz_fb-jz6t3bA",1793046312647]