@wcstack/upload 4.5.0 → 4.6.1
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.
- package/README.ja.md +1 -1
- package/README.md +1 -1
- package/dist/auto.d.ts +2 -0
- package/dist/auto.min.js +1 -1
- package/dist/auto.min.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +43 -16
- package/dist/index.esm.js.map +1 -1
- package/package.json +5 -2
package/README.ja.md
CHANGED
|
@@ -110,7 +110,7 @@ npm install @wcstack/upload
|
|
|
110
110
|
|
|
111
111
|
観測できるのは `false` へのリセットのみです。`true` 遷移(アップロード開始)は `wcs-upload:trigger-changed` を発火しません。バインディングシステムは `true` を書き込んで開始し、唯一の `false` エッジを観測してコマンドの完了を知ります。これは `@wcstack/fetch` の `trigger` と同じトレードオフです。
|
|
112
112
|
|
|
113
|
-
**`files` はアップロードで使い切ります。** `@wcstack/fetch` の `body` と同じです。アップロードが終わると(成功・失敗・中断のどれでも)`files` は `null` に戻り、`wcs-upload:files-changed` がそれを運ぶので、双方向の `files:` 束縛はそのパスも空にします。送り直すには、ファイルをもう一度代入してから `trigger` を書いてください。また `trigger` は書かれたときに `url` と `files` を読みます。1 つの `data-wcs` では、それらの後に書いてください(`url: …; files: …; trigger: …` — 束縛は書いた順に当たります)。ファイルか `url` の無い `trigger`(や `upload()`)は何も送らず、`error` も立てません。4.5 から、要素と理由ごとに 1 回警告します(`[wcs/command-not-ready]
|
|
113
|
+
**`files` はアップロードで使い切ります。** `@wcstack/fetch` の `body` と同じです。アップロードが終わると(成功・失敗・中断のどれでも)`files` は `null` に戻り、`wcs-upload:files-changed` がそれを運ぶので、双方向の `files:` 束縛はそのパスも空にします。送り直すには、ファイルをもう一度代入してから `trigger` を書いてください。また `trigger` は書かれたときに `url` と `files` を読みます。1 つの `data-wcs` では、それらの後に書いてください(`url: …; files: …; trigger: …` — 束縛は書いた順に当たります)。ファイルか `url` の無い `trigger`(や `upload()`)は何も送らず、`error` も立てません。4.5 から、要素と理由ごとに 1 回警告します(`[wcs/command-not-ready]`)。4.6 から、`url` がまだ無い自動送信の `<wcs-upload>` に代入したファイルは url を待ち、url が来たときに送られます(以前は送られず、要素が警告していました)。フレームワークの props も書いた順に当たるので、JSX の `files={files} url=…` も `url=… files={files}` と同じく送るようになりました。
|
|
114
114
|
|
|
115
115
|
### 3. 宣言的なトリガーターゲット
|
|
116
116
|
|
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ Use `manual` when you want to choose files first and upload later.
|
|
|
110
110
|
|
|
111
111
|
Only the `false` reset is observable: the `true` transition (upload start) does **not** dispatch `wcs-upload:trigger-changed`. A binding system writes `true` to start and observes the single `false` edge to know the command finished. This is the same trade-off as `@wcstack/fetch`'s `trigger`.
|
|
112
112
|
|
|
113
|
-
**`files` are used up by an upload**, as `@wcstack/fetch`'s `body` is: once an upload settles (success, failure or abort), `files` goes back to `null` and `wcs-upload:files-changed` carries it, so a two-way `files:` binding clears its path too. To retry, assign the files again, then write `trigger`. And `trigger` reads `url` and `files` when it is written: in one `data-wcs`, write it after them (`url: …; files: …; trigger: …` — bindings apply in the order written). A `trigger` (or `upload()`) without files or a `url` sends nothing and sets no `error`; since 4.5 it warns once per element and reason (`[wcs/command-not-ready]`)
|
|
113
|
+
**`files` are used up by an upload**, as `@wcstack/fetch`'s `body` is: once an upload settles (success, failure or abort), `files` goes back to `null` and `wcs-upload:files-changed` carries it, so a two-way `files:` binding clears its path too. To retry, assign the files again, then write `trigger`. And `trigger` reads `url` and `files` when it is written: in one `data-wcs`, write it after them (`url: …; files: …; trigger: …` — bindings apply in the order written). A `trigger` (or `upload()`) without files or a `url` sends nothing and sets no `error`; since 4.5 it warns once per element and reason (`[wcs/command-not-ready]`). Since 4.6, files assigned to an automatic `<wcs-upload>` that has no `url` yet wait for it and are sent when it arrives (before, they were not sent and the element warned): a framework's props are applied in the order written too, and `files={files} url=…` in JSX now uploads as `url=… files={files}` does.
|
|
114
114
|
|
|
115
115
|
### 3. Declarative trigger target
|
|
116
116
|
|
package/dist/auto.d.ts
ADDED
package/dist/auto.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const t={triggerAttribute:"data-uploadtarget",tagNames:{upload:"wcs-upload"}};class e{laneKey;policy;_ownerGeneration=0;_latestEpoch=0;_nextOperationId=1;_activeOperationId=void 0;_activeOperationIds=new Set;_queue=[];_inFlightCount=0;_terminal=new Map;_claimedOutcome=new Map;_controllers=new Map;_attempts=new Map;_withSignal;_trace;constructor(t,e,s={}){this.laneKey=t,this.policy=e,this._withSignal=s.withSignal??!1,this._trace=s.trace}get ownerGeneration(){return this._ownerGeneration}get inFlightCount(){return this._inFlightCount}get latestEpoch(){return this._latestEpoch}get activeOperationId(){return this._activeOperationId}begin(){let t;switch(this.policy){case"latest":t=++this._latestEpoch,void 0!==this._activeOperationId&&this._abortController(this._activeOperationId);break;case"exhaust":if(void 0!==this._activeOperationId)return null}const e=this._nextOperationId++,s={operationId:e,ownerGeneration:this._ownerGeneration,laneKey:this.laneKey,policy:this.policy,supersedeEpoch:t};switch(this.policy){case"latest":case"exhaust":this._activeOperationId=e;break;case"queue":this._queue.push(s),void 0===this._activeOperationId&&(this._activeOperationId=e);break;case"overlap":this._activeOperationIds.add(e)}this._inFlightCount+=1,this._attempts.set(e,1);const i=this._makeAttempt(e,1);return void 0!==this._trace&&this._trace({type:"io:operation-started",operationId:e,laneKey:this.laneKey,policy:this.policy}),{ticket:s,attempt:i}}retry(t){if(t.ownerGeneration!==this._ownerGeneration)return null;if(this._terminal.has(t.operationId))return null;const e=this._attempts.get(t.operationId);if(void 0===e)return null;const s=e+1;this._attempts.set(t.operationId,s),this._releaseController(t.operationId);const i=this._makeAttempt(t.operationId,s);return void 0!==this._trace&&this._trace({type:"io:operation-retried",operationId:t.operationId,laneKey:this.laneKey,attempt:s}),i}canCommit(t){if(t.ownerGeneration!==this._ownerGeneration)return!1;const e=this._terminal.get(t.operationId);return(void 0===e||"committing"===e)&&this._isEligible(t)}claimTerminal(t,e){return t.ownerGeneration===this._ownerGeneration&&(!this._terminal.has(t.operationId)&&(!!this._isEligible(t)&&(this._terminal.set(t.operationId,"committing"),this._claimedOutcome.set(t.operationId,e),!0)))}claimedOutcome(t){return this._claimedOutcome.get(t.operationId)}finalize(t){const e=t.operationId,s=this._terminal.get(e);if(void 0!==s&&"committing"!==s)return;let i;i="committing"===s?this._claimedOutcome.get(e)??"stale":"stale",this._terminal.set(e,i),this._claimedOutcome.delete(e),this._releaseController(e),this._attempts.delete(e),this._inFlightCount>0&&(this._inFlightCount-=1),this._advanceBookkeeping(e),void 0!==this._trace&&("stale"===i?this._trace({type:"io:stale-dropped",operationId:e,laneKey:this.laneKey}):this._trace({type:"io:operation-settled",operationId:e,laneKey:this.laneKey,outcome:i}))}signalOf(t){return this._controllers.get(t.operationId)?.signal}abort(t){this._abortController(t.operationId)}abortActive(){void 0!==this._activeOperationId&&this._abortController(this._activeOperationId);for(const t of this._activeOperationIds)this._abortController(t)}disposeOwner(){this._ownerGeneration+=1;for(const t of Array.from(this._controllers.keys()))this._abortController(t),this._releaseController(t);for(const t of Array.from(this._attempts.keys()))this._terminal.has(t)||this._terminal.set(t,"stale"),this._claimedOutcome.delete(t),this._attempts.delete(t),void 0!==this._trace&&this._trace({type:"io:stale-dropped",operationId:t,laneKey:this.laneKey});this._activeOperationId=void 0,this._activeOperationIds.clear(),this._queue.length=0,this._inFlightCount=0}_makeAttempt(t,e){let s;if(this._withSignal&&"function"==typeof AbortController){const e=new AbortController;this._controllers.set(t,e),s=e.signal}return{operationId:t,attempt:e,signal:s}}_isEligible(t){switch(this.policy){case"latest":return t.supersedeEpoch===this._latestEpoch;case"queue":case"exhaust":return this._activeOperationId===t.operationId;case"overlap":return this._activeOperationIds.has(t.operationId)}}_advanceBookkeeping(t){switch(this.policy){case"latest":case"exhaust":this._activeOperationId===t&&(this._activeOperationId=void 0);break;case"queue":{const e=this._queue.filter(e=>e.operationId!==t);this._queue.length=0,this._queue.push(...e),this._activeOperationId=this._queue.length>0?this._queue[0].operationId:void 0;break}case"overlap":this._activeOperationIds.delete(t)}}_abortController(t){const e=this._controllers.get(t);void 0===e||e.signal.aborted||e.abort()}_releaseController(t){this._controllers.delete(t)}}function s(t,e){const s=new Map,i=e=>{const s=t.get(e);return void 0===s?"unknown":s.probe()?"available":"missing"};let r=!0;for(const t of e.required){const e=i(t);s.set(t,e),"available"!==e&&(r=!1)}let n=!0;for(const t of e.optional??[]){const e=i(t);s.set(t,e),"available"!==e&&(n=!1)}const a=r?n?"ready":"degraded":"idle",o=[...e.required,...e.optional??[]],l=o.some(e=>!0===t.get(e)?.requiresSecureContext),c=o.some(e=>!0===t.get(e)?.requiresUserActivation),h=l?!0===globalThis.isSecureContext?"satisfied":"required":"not-applicable",u=c?"required":"not-applicable";return{availability:s,permission:e.permission??"not-applicable",readiness:a,activity:e.activity??"inactive",preconditions:{secureContext:h,userActivation:u},epoch:e.epoch??0,lastError:e.lastError}}function i(t,e){return e.every(e=>"available"===t.availability.get(e))}const r="capability-missing",n="invalid-argument",a="network",o="http-error",l=new Map([["web.xhr",{probe:()=>"function"==typeof globalThis.XMLHttpRequest,compatKey:"api.XMLHttpRequest"}]]);class c extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:"wcs-upload:response",semantics:"state",getter:t=>t.detail.value},{name:"loading",event:"wcs-upload:loading-changed",semantics:"state"},{name:"progress",event:"wcs-upload:progress",semantics:"state"},{name:"error",event:"wcs-upload:error",semantics:"state"},{name:"status",event:"wcs-upload:response",semantics:"state",getter:t=>t.detail.status},{name:"errorInfo",event:"wcs-upload:error-info-changed",semantics:"state"}],inputs:[{name:"url"},{name:"method"},{name:"fieldName"}],commands:[{name:"upload",async:!0},{name:"abort"}]};static REQUIRED_CAPABILITIES=["web.xhr"];_target;_value=null;_loading=!1;_progress=0;_error=null;_status=0;_errorInfo=null;_xhr=null;_promise=Promise.resolve(null);_lane=new e("upload","latest",{withSignal:!1});_ready=Promise.resolve();constructor(t){super(),this._target=t??this}get ready(){return this._ready}observe(){return this._ready}dispose(){this._lane.disposeOwner(),this.abort(),this._loading&&this._setLoading(!1)}get value(){return this._value}get loading(){return this._loading}get progress(){return this._progress}get error(){return this._error}get status(){return this._status}get promise(){return this._promise}get errorInfo(){return this._errorInfo}get supported(){return i(this.platformAssessment,c.REQUIRED_CAPABILITIES)}get platformAssessment(){return s(l,{required:c.REQUIRED_CAPABILITIES,activity:this._loading?"active":"inactive",lastError:this._errorInfo??void 0})}_commitStep(t,e){this._lane.canCommit(t)&&e()}_setLoading(t){this._loading=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:loading-changed",{detail:t,bubbles:!0}))}_setProgress(t){this._progress=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:progress",{detail:t,bubbles:!0}))}_setError(t){this._error!==t&&(this._error=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:error",{detail:t,bubbles:!0})))}setError(t){this._setError(t)}_setResponse(t,e){this._value=t,this._status=e,this._target.dispatchEvent(new CustomEvent("wcs-upload:response",{detail:{value:t,status:e},bubbles:!0}))}_setErrorInfo(t,e,s,i,r){this._commitErrorInfo({code:t,phase:e,recoverable:s,message:i,...void 0===r?{}:{capabilityId:r}})}_commitErrorInfo(t){this._errorInfo!==t&&(this._errorInfo=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:error-info-changed",{detail:t,bubbles:!0})))}abort(){this._xhr&&(this._xhr.abort(),this._xhr=null)}async upload(t,e,s={}){if(!t)return this._setErrorInfo(n,"start",!1,"url is required."),this._setError({message:"url is required."}),null;if(!e||0===e.length)return this._setErrorInfo(n,"start",!1,"files are required."),this._setError({message:"files are required."}),null;const i=this._doUpload(t,e,s);return this._promise=i,i}_doUpload(t,e,s){const n=this.platformAssessment;if(!i(n,c.REQUIRED_CAPABILITIES)){const t=c.REQUIRED_CAPABILITIES.find(t=>"available"!==n.availability.get(t)),e=`Required capability "${t}" is unavailable.`;return this._setErrorInfo(r,"start",!1,e,t),this._setError({message:e}),Promise.resolve(null)}this.abort();const l=this._lane.begin(),{ticket:h}=l;this._commitStep(h,()=>this._setLoading(!0)),this._commitStep(h,()=>{this._setProgress(0),this._commitErrorInfo(null),this._setError(null)});const{method:u="POST",headers:d={},fieldName:p="file"}=s,_=new FormData;for(let t=0;t<e.length;t++)_.append(p,e[t]);return new Promise(e=>{const s=new XMLHttpRequest;this._xhr=s,s.upload.addEventListener("progress",t=>{this._commitStep(h,()=>{t.lengthComputable&&this._setProgress(Math.round(t.loaded/t.total*100))})}),s.addEventListener("load",()=>{if(this._xhr=null,s.status>=200&&s.status<300){if(!this._lane.claimTerminal(h,"success"))return e(null),void this._lane.finalize(h);let t=s.responseText;if((s.getResponseHeader("Content-Type")||"").includes("application/json"))try{t=JSON.parse(s.responseText)}catch{}this._commitStep(h,()=>this._setProgress(100)),this._commitStep(h,()=>this._setResponse(t,s.status)),this._commitStep(h,()=>this._setLoading(!1)),this._lane.finalize(h),e(t)}else{if(!this._lane.claimTerminal(h,"error"))return e(null),void this._lane.finalize(h);const t={status:s.status,statusText:s.statusText,body:s.responseText};this._commitStep(h,()=>{this._status=s.status,this._setErrorInfo(o,"execute",!0,`HTTP ${s.status} ${s.statusText}`),this._setError(t)}),this._commitStep(h,()=>this._setLoading(!1)),this._lane.finalize(h),e(null)}}),s.addEventListener("error",()=>{if(this._xhr=null,!this._lane.claimTerminal(h,"error"))return e(null),void this._lane.finalize(h);const t="Network error";this._commitStep(h,()=>{this._setErrorInfo(a,"execute",!0,t),this._setError({message:t})}),this._commitStep(h,()=>this._setLoading(!1)),this._lane.finalize(h),e(null)}),s.addEventListener("abort",()=>{this._xhr=null,this._lane.claimTerminal(h,"aborted")&&this._commitStep(h,()=>this._setLoading(!1)),this._lane.finalize(h),e(null)}),s.open(u,t);for(const[t,e]of Object.entries(d))s.setRequestHeader(t,e);s.send(_)})}}let h=!1;function u(e){const s=e.target;if(!(s instanceof Element))return;const i=s.closest(`[${t.triggerAttribute}]`);if(!i)return;const r=i.getAttribute(t.triggerAttribute);if(!r)return;const n=customElements.get(t.tagNames.upload),a=document.getElementById(r);if(!(n&&a instanceof n))return;const o=a;o.files&&o.files.length>0&&o.url&&e.preventDefault(),o.upload()}function d(t,e){let s=Object.getPrototypeOf(t);for(;null!==s;){const t=Object.getOwnPropertyDescriptor(s,e);if(void 0!==t)return"function"==typeof t.get||"function"==typeof t.set;s=Object.getPrototypeOf(s)}return!1}const p=new WeakMap;function _(t,e){let s=p.get(t);return void 0===s&&(s=new Map,p.set(t,s)),s.has(e)||s.set(e,t.getAttribute(e)),s.get(e)}function m(t,e,s){null===s?t.removeAttribute(e):t.setAttribute(e,s)}function g(t,e,s){const i=_(t,e);m(t,e,void 0===s?i:null===s?null:String(s))}function f(t,e,s){const i=_(t,e);m(t,e,void 0===s?i:s?"":null)}class b extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...c.wcBindable,properties:[...c.wcBindable.properties,{name:"trigger",event:"wcs-upload:trigger-changed",semantics:"state"},{name:"files",event:"wcs-upload:files-changed",semantics:"state"}],inputs:[{name:"url"},{name:"method"},{name:"fieldName"},{name:"multiple"},{name:"maxSize"},{name:"accept"},{name:"manual"},{name:"files"},{name:"trigger"}]};static get observedAttributes(){return["url"]}_core;_files=null;_trigger=!1;_told=null;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new c(this),this._internals=this._initInternals(),this._wireStates({"wcs-upload:loading-changed":t=>({loading:!0===t}),"wcs-upload:error":t=>({error:null!=t})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const t=this.attachInternals();return t.states.add("wcs-probe"),t.states.delete("wcs-probe"),t}catch{return null}}_wireStates(t){if(null===this._internals)return;const e=this._internals.states;for(const[s,i]of Object.entries(t))this.addEventListener(s,t=>{const s=this.hasAttribute("debug-states");for(const[r,n]of Object.entries(i(t.detail))){try{n?e.add(r):e.delete(r)}catch{}s&&this.toggleAttribute(`data-wcs-state-${r}`,n)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}get url(){return this.getAttribute("url")||""}set url(t){g(this,"url",t)}get method(){return(this.getAttribute("method")||"POST").toUpperCase()}set method(t){g(this,"method",t)}get fieldName(){return this.getAttribute("field-name")||"file"}set fieldName(t){g(this,"field-name",t)}get multiple(){return this.hasAttribute("multiple")}set multiple(t){f(this,"multiple",t)}get maxSize(){const t=this.getAttribute("max-size");if(null===t)return 1/0;const e=parseInt(t,10);return Number.isFinite(e)&&e>=0?e:1/0}set maxSize(t){g(this,"max-size",t)}get accept(){return this.getAttribute("accept")||""}set accept(t){g(this,"accept",t)}get manual(){return this.hasAttribute("manual")}set manual(t){f(this,"manual",t)}get value(){return this._core.value}get loading(){return this._core.loading}get progress(){return this._core.progress}get error(){return this._core.error}get status(){return this._core.status}get errorInfo(){return this._core.errorInfo}get promise(){return this._core.promise}get trigger(){return this._trigger}set trigger(t){!!t&&(this._trigger=!0,this.upload().finally(()=>{this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-upload:trigger-changed",{detail:!1,bubbles:!0}))}))}get files(){return this._files}set files(t){const e=t??null;this._files=e,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:e,bubbles:!0})),!this.manual&&e&&e.length>0&&(this.url?this.upload():this._warnNotReady("files were assigned while there is no url"))}_validate(t){const e=this.maxSize;if(e!==1/0)for(let s=0;s<t.length;s++)if(t[s].size>e)return{message:`File "${t[s].name}" exceeds maximum size of ${e} bytes.`};const s=this.accept;if(s){const e=s.split(",").map(t=>t.trim().toLowerCase());for(let i=0;i<t.length;i++){const r=t[i],n=r.type.toLowerCase(),a=r.name.toLowerCase();if(!e.some(t=>t.startsWith(".")?a.endsWith(t):t.endsWith("/*")?""!==n&&n.startsWith(t.slice(0,-1)):""!==n&&n===t))return{message:`File "${r.name}" does not match accepted types: ${s}`}}}return null}abort(){this._core.abort()}async upload(){const t=this._files;if(!t||0===t.length||!this.url)return this._warnNotReady(this.url?"there are no files":"there is no url"),null;const e=this._validate(t);if(e)return this._core.setError(e),null;const s=await this._core.upload(this.url,t,{method:this.method,fieldName:this.fieldName});return this._files===t&&(this._files=null,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:null,bubbles:!0}))),s}_warnNotReady(t){this._told?.has(t)||((this._told??=new Set).add(t),console.warn(`[@wcstack/upload] [wcs/command-not-ready] The upload was refused: ${t}, so nothing is sent. Write url and files before trigger (bindings apply in the order written), and assign files again for each retry: an upload uses them up. (Said once per element and reason.)`,this))}attributeChangedCallback(t,e,s){}connectedCallback(){!function(t){const e=t.constructor?.wcBindable,s=e?.inputs;if(void 0!==s)for(const e of s){const s=e.name;if(!Object.prototype.hasOwnProperty.call(t,s))continue;if(!d(t,s))continue;const i=t,r=i[s];delete i[s],i[s]=r}}(this),this.style.display="none",h||(h=!0,document.addEventListener("click",u)),this._connectedCallbackPromise=this._core.observe()}disconnectedCallback(){this._core.dispose()}}var v;!function(e=customElements){e.get(t.tagNames.upload)||e.define(t.tagNames.upload,b)}(v);
|
|
1
|
+
const t={triggerAttribute:"data-uploadtarget",tagNames:{upload:"wcs-upload"}};class e{laneKey;policy;_ownerGeneration=0;_latestEpoch=0;_nextOperationId=1;_activeOperationId=void 0;_activeOperationIds=new Set;_queue=[];_inFlightCount=0;_terminal=new Map;_claimedOutcome=new Map;_controllers=new Map;_attempts=new Map;_withSignal;_trace;constructor(t,e,i={}){this.laneKey=t,this.policy=e,this._withSignal=i.withSignal??!1,this._trace=i.trace}get ownerGeneration(){return this._ownerGeneration}get inFlightCount(){return this._inFlightCount}get latestEpoch(){return this._latestEpoch}get activeOperationId(){return this._activeOperationId}begin(){let t;switch(this.policy){case"latest":t=++this._latestEpoch,void 0!==this._activeOperationId&&this._abortController(this._activeOperationId);break;case"exhaust":if(void 0!==this._activeOperationId)return null}const e=this._nextOperationId++,i={operationId:e,ownerGeneration:this._ownerGeneration,laneKey:this.laneKey,policy:this.policy,supersedeEpoch:t};switch(this.policy){case"latest":case"exhaust":this._activeOperationId=e;break;case"queue":this._queue.push(i),void 0===this._activeOperationId&&(this._activeOperationId=e);break;case"overlap":this._activeOperationIds.add(e)}this._inFlightCount+=1,this._attempts.set(e,1);const s=this._makeAttempt(e,1);return void 0!==this._trace&&this._trace({type:"io:operation-started",operationId:e,laneKey:this.laneKey,policy:this.policy}),{ticket:i,attempt:s}}retry(t){if(t.ownerGeneration!==this._ownerGeneration)return null;if(this._terminal.has(t.operationId))return null;const e=this._attempts.get(t.operationId);if(void 0===e)return null;const i=e+1;this._attempts.set(t.operationId,i),this._releaseController(t.operationId);const s=this._makeAttempt(t.operationId,i);return void 0!==this._trace&&this._trace({type:"io:operation-retried",operationId:t.operationId,laneKey:this.laneKey,attempt:i}),s}canCommit(t){if(t.ownerGeneration!==this._ownerGeneration)return!1;const e=this._terminal.get(t.operationId);return(void 0===e||"committing"===e)&&this._isEligible(t)}claimTerminal(t,e){return t.ownerGeneration===this._ownerGeneration&&(!this._terminal.has(t.operationId)&&(!!this._isEligible(t)&&(this._terminal.set(t.operationId,"committing"),this._claimedOutcome.set(t.operationId,e),!0)))}claimedOutcome(t){return this._claimedOutcome.get(t.operationId)}finalize(t){const e=t.operationId,i=this._terminal.get(e);if(void 0!==i&&"committing"!==i)return;let s;s="committing"===i?this._claimedOutcome.get(e)??"stale":"stale",this._terminal.set(e,s),this._claimedOutcome.delete(e),this._releaseController(e),this._attempts.delete(e),this._inFlightCount>0&&(this._inFlightCount-=1),this._advanceBookkeeping(e),void 0!==this._trace&&("stale"===s?this._trace({type:"io:stale-dropped",operationId:e,laneKey:this.laneKey}):this._trace({type:"io:operation-settled",operationId:e,laneKey:this.laneKey,outcome:s}))}signalOf(t){return this._controllers.get(t.operationId)?.signal}abort(t){this._abortController(t.operationId)}abortActive(){void 0!==this._activeOperationId&&this._abortController(this._activeOperationId);for(const t of this._activeOperationIds)this._abortController(t)}disposeOwner(){this._ownerGeneration+=1;for(const t of Array.from(this._controllers.keys()))this._abortController(t),this._releaseController(t);for(const t of Array.from(this._attempts.keys()))this._terminal.has(t)||this._terminal.set(t,"stale"),this._claimedOutcome.delete(t),this._attempts.delete(t),void 0!==this._trace&&this._trace({type:"io:stale-dropped",operationId:t,laneKey:this.laneKey});this._activeOperationId=void 0,this._activeOperationIds.clear(),this._queue.length=0,this._inFlightCount=0}_makeAttempt(t,e){let i;if(this._withSignal&&"function"==typeof AbortController){const e=new AbortController;this._controllers.set(t,e),i=e.signal}return{operationId:t,attempt:e,signal:i}}_isEligible(t){switch(this.policy){case"latest":return t.supersedeEpoch===this._latestEpoch;case"queue":case"exhaust":return this._activeOperationId===t.operationId;case"overlap":return this._activeOperationIds.has(t.operationId)}}_advanceBookkeeping(t){switch(this.policy){case"latest":case"exhaust":this._activeOperationId===t&&(this._activeOperationId=void 0);break;case"queue":{const e=this._queue.filter(e=>e.operationId!==t);this._queue.length=0,this._queue.push(...e),this._activeOperationId=this._queue.length>0?this._queue[0].operationId:void 0;break}case"overlap":this._activeOperationIds.delete(t)}}_abortController(t){const e=this._controllers.get(t);void 0===e||e.signal.aborted||e.abort()}_releaseController(t){this._controllers.delete(t)}}function i(t,e){const i=new Map,s=e=>{const i=t.get(e);return void 0===i?"unknown":i.probe()?"available":"missing"};let r=!0;for(const t of e.required){const e=s(t);i.set(t,e),"available"!==e&&(r=!1)}let n=!0;for(const t of e.optional??[]){const e=s(t);i.set(t,e),"available"!==e&&(n=!1)}const a=r?n?"ready":"degraded":"idle",o=[...e.required,...e.optional??[]],l=o.some(e=>!0===t.get(e)?.requiresSecureContext),c=o.some(e=>!0===t.get(e)?.requiresUserActivation),h=l?!0===globalThis.isSecureContext?"satisfied":"required":"not-applicable",u=c?"required":"not-applicable";return{availability:i,permission:e.permission??"not-applicable",readiness:a,activity:e.activity??"inactive",preconditions:{secureContext:h,userActivation:u},epoch:e.epoch??0,lastError:e.lastError}}function s(t,e){return e.every(e=>"available"===t.availability.get(e))}const r="capability-missing",n="invalid-argument",a="network",o="http-error",l=new Map([["web.xhr",{probe:()=>"function"==typeof globalThis.XMLHttpRequest,compatKey:"api.XMLHttpRequest"}]]);class c extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:"wcs-upload:response",semantics:"state",getter:t=>t.detail.value},{name:"loading",event:"wcs-upload:loading-changed",semantics:"state"},{name:"progress",event:"wcs-upload:progress",semantics:"state"},{name:"error",event:"wcs-upload:error",semantics:"state"},{name:"status",event:"wcs-upload:response",semantics:"state",getter:t=>t.detail.status},{name:"errorInfo",event:"wcs-upload:error-info-changed",semantics:"state"}],inputs:[{name:"url"},{name:"method"},{name:"fieldName"}],commands:[{name:"upload",async:!0},{name:"abort"}]};static REQUIRED_CAPABILITIES=["web.xhr"];_target;_value=null;_loading=!1;_progress=0;_error=null;_status=0;_errorInfo=null;_xhr=null;_promise=Promise.resolve(null);_lane=new e("upload","latest",{withSignal:!1});_ready=Promise.resolve();constructor(t){super(),this._target=t??this}get ready(){return this._ready}observe(){return this._ready}dispose(){this._lane.disposeOwner(),this.abort(),this._loading&&this._setLoading(!1)}get value(){return this._value}get loading(){return this._loading}get progress(){return this._progress}get error(){return this._error}get status(){return this._status}get promise(){return this._promise}get errorInfo(){return this._errorInfo}get supported(){return s(this.platformAssessment,c.REQUIRED_CAPABILITIES)}get platformAssessment(){return i(l,{required:c.REQUIRED_CAPABILITIES,activity:this._loading?"active":"inactive",lastError:this._errorInfo??void 0})}_commitStep(t,e){this._lane.canCommit(t)&&e()}_setLoading(t){this._loading=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:loading-changed",{detail:t,bubbles:!0}))}_setProgress(t){this._progress=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:progress",{detail:t,bubbles:!0}))}_setError(t){this._error!==t&&(this._error=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:error",{detail:t,bubbles:!0})))}setError(t){this._setError(t)}_setResponse(t,e){this._value=t,this._status=e,this._target.dispatchEvent(new CustomEvent("wcs-upload:response",{detail:{value:t,status:e},bubbles:!0}))}_setErrorInfo(t,e,i,s,r){this._commitErrorInfo({code:t,phase:e,recoverable:i,message:s,...void 0===r?{}:{capabilityId:r}})}_commitErrorInfo(t){this._errorInfo!==t&&(this._errorInfo=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:error-info-changed",{detail:t,bubbles:!0})))}abort(){this._xhr&&(this._xhr.abort(),this._xhr=null)}async upload(t,e,i={}){if(!t)return this._setErrorInfo(n,"start",!1,"url is required."),this._setError({message:"url is required."}),null;if(!e||0===e.length)return this._setErrorInfo(n,"start",!1,"files are required."),this._setError({message:"files are required."}),null;const s=this._doUpload(t,e,i);return this._promise=s,s}_doUpload(t,e,i){const n=this.platformAssessment;if(!s(n,c.REQUIRED_CAPABILITIES)){const t=c.REQUIRED_CAPABILITIES.find(t=>"available"!==n.availability.get(t)),e=`Required capability "${t}" is unavailable.`;return this._setErrorInfo(r,"start",!1,e,t),this._setError({message:e}),Promise.resolve(null)}this.abort();const l=this._lane.begin(),{ticket:h}=l;this._commitStep(h,()=>this._setLoading(!0)),this._commitStep(h,()=>{this._setProgress(0),this._commitErrorInfo(null),this._setError(null)});const{method:u="POST",headers:d={},fieldName:p="file"}=i,_=new FormData;for(let t=0;t<e.length;t++)_.append(p,e[t]);return new Promise(e=>{const i=new XMLHttpRequest;this._xhr=i,i.upload.addEventListener("progress",t=>{this._commitStep(h,()=>{t.lengthComputable&&this._setProgress(Math.round(t.loaded/t.total*100))})}),i.addEventListener("load",()=>{if(this._xhr=null,i.status>=200&&i.status<300){if(!this._lane.claimTerminal(h,"success"))return e(null),void this._lane.finalize(h);let t=i.responseText;if((i.getResponseHeader("Content-Type")||"").includes("application/json"))try{t=JSON.parse(i.responseText)}catch{}this._commitStep(h,()=>this._setProgress(100)),this._commitStep(h,()=>this._setResponse(t,i.status)),this._commitStep(h,()=>this._setLoading(!1)),this._lane.finalize(h),e(t)}else{if(!this._lane.claimTerminal(h,"error"))return e(null),void this._lane.finalize(h);const t={status:i.status,statusText:i.statusText,body:i.responseText};this._commitStep(h,()=>{this._status=i.status,this._setErrorInfo(o,"execute",!0,`HTTP ${i.status} ${i.statusText}`),this._setError(t)}),this._commitStep(h,()=>this._setLoading(!1)),this._lane.finalize(h),e(null)}}),i.addEventListener("error",()=>{if(this._xhr=null,!this._lane.claimTerminal(h,"error"))return e(null),void this._lane.finalize(h);const t="Network error";this._commitStep(h,()=>{this._setErrorInfo(a,"execute",!0,t),this._setError({message:t})}),this._commitStep(h,()=>this._setLoading(!1)),this._lane.finalize(h),e(null)}),i.addEventListener("abort",()=>{this._xhr=null,this._lane.claimTerminal(h,"aborted")&&this._commitStep(h,()=>this._setLoading(!1)),this._lane.finalize(h),e(null)}),i.open(u,t);for(const[t,e]of Object.entries(d))i.setRequestHeader(t,e);i.send(_)})}}let h=!1;function u(e){const i=e.target;if(!(i instanceof Element))return;const s=i.closest(`[${t.triggerAttribute}]`);if(!s)return;const r=s.getAttribute(t.triggerAttribute);if(!r)return;const n=customElements.get(t.tagNames.upload),a=document.getElementById(r);if(!(n&&a instanceof n))return;const o=a;o.files&&o.files.length>0&&o.url&&e.preventDefault(),o.upload()}function d(t,e){let i=Object.getPrototypeOf(t);for(;null!==i;){const t=Object.getOwnPropertyDescriptor(i,e);if(void 0!==t)return"function"==typeof t.get||"function"==typeof t.set;i=Object.getPrototypeOf(i)}return!1}const p=new WeakSet;function _(t,e,i){if(p.has(t))return;p.add(t);const s=t.localName??"element";console.warn(`[wcs/input-as-attribute] <${s}> has the attribute ${e}="${i}": an object was written as an attribute, so the element did not receive it. A framework does that when the property is set before the element's definition loads (React 19), or when told to (Vue's .attr). Load the definition before rendering, or assign the property through a ref (Vue: .prop). (Said once per element.)`,t)}const m=new WeakMap;function g(t,e){let i=m.get(t);return void 0===i&&(i=new Map,m.set(t,i)),i.has(e)||i.set(e,t.getAttribute(e)),i.get(e)}function f(t,e,i){null===i?t.removeAttribute(e):t.setAttribute(e,i)}function b(t,e,i){const s=g(t,e);f(t,e,void 0===i?s:null===i?null:String(i))}function v(t,e,i){const s=g(t,e);f(t,e,void 0===i?s:i?"":null)}class w extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...c.wcBindable,properties:[...c.wcBindable.properties,{name:"trigger",event:"wcs-upload:trigger-changed",semantics:"state"},{name:"files",event:"wcs-upload:files-changed",semantics:"state"}],inputs:[{name:"url"},{name:"method"},{name:"fieldName"},{name:"multiple"},{name:"maxSize"},{name:"accept"},{name:"manual"},{name:"files"},{name:"trigger"}]};static get observedAttributes(){return["url"]}_core;_files=null;_trigger=!1;_told=null;_waitingForUrl=!1;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new c(this),this._internals=this._initInternals(),this._wireStates({"wcs-upload:loading-changed":t=>({loading:!0===t}),"wcs-upload:error":t=>({error:null!=t})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const t=this.attachInternals();return t.states.add("wcs-probe"),t.states.delete("wcs-probe"),t}catch{return null}}_wireStates(t){if(null===this._internals)return;const e=this._internals.states;for(const[i,s]of Object.entries(t))this.addEventListener(i,t=>{const i=this.hasAttribute("debug-states");for(const[r,n]of Object.entries(s(t.detail))){try{n?e.add(r):e.delete(r)}catch{}i&&this.toggleAttribute(`data-wcs-state-${r}`,n)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}get url(){return this.getAttribute("url")||""}set url(t){b(this,"url",t)}get method(){return(this.getAttribute("method")||"POST").toUpperCase()}set method(t){b(this,"method",t)}get fieldName(){return this.getAttribute("field-name")||"file"}set fieldName(t){b(this,"field-name",t)}get multiple(){return this.hasAttribute("multiple")}set multiple(t){v(this,"multiple",t)}get maxSize(){const t=this.getAttribute("max-size");if(null===t)return 1/0;const e=parseInt(t,10);return Number.isFinite(e)&&e>=0?e:1/0}set maxSize(t){b(this,"max-size",t)}get accept(){return this.getAttribute("accept")||""}set accept(t){b(this,"accept",t)}get manual(){return this.hasAttribute("manual")}set manual(t){v(this,"manual",t)}get value(){return this._core.value}get loading(){return this._core.loading}get progress(){return this._core.progress}get error(){return this._core.error}get status(){return this._core.status}get errorInfo(){return this._core.errorInfo}get promise(){return this._core.promise}get trigger(){return this._trigger}set trigger(t){!!t&&(this._trigger=!0,this.upload().finally(()=>{this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-upload:trigger-changed",{detail:!1,bubbles:!0}))}))}get files(){return this._files}set files(t){const e=t??null;this._files=e,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:e,bubbles:!0})),this._waitingForUrl=!this.manual&&!!e&&e.length>0&&!this.url,!this.manual&&e&&e.length>0&&this.url&&this.upload()}_validate(t){const e=this.maxSize;if(e!==1/0)for(let i=0;i<t.length;i++)if(t[i].size>e)return{message:`File "${t[i].name}" exceeds maximum size of ${e} bytes.`};const i=this.accept;if(i){const e=i.split(",").map(t=>t.trim().toLowerCase());for(let s=0;s<t.length;s++){const r=t[s],n=r.type.toLowerCase(),a=r.name.toLowerCase();if(!e.some(t=>t.startsWith(".")?a.endsWith(t):t.endsWith("/*")?""!==n&&n.startsWith(t.slice(0,-1)):""!==n&&n===t))return{message:`File "${r.name}" does not match accepted types: ${i}`}}}return null}abort(){this._core.abort()}async upload(){const t=this._files;if(!t||0===t.length||!this.url)return this._warnNotReady(this.url?"there are no files":"there is no url"),null;const e=this._validate(t);if(e)return this._core.setError(e),null;const i=await this._core.upload(this.url,t,{method:this.method,fieldName:this.fieldName});return this._files===t&&(this._files=null,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:null,bubbles:!0}))),i}_warnNotReady(t){this._told?.has(t)||((this._told??=new Set).add(t),console.warn(`[@wcstack/upload] [wcs/command-not-ready] The upload was refused: ${t}, so nothing is sent. Write url and files before trigger (data-wcs bindings and a framework's props are applied in the order written), and assign files again for each retry: an upload uses them up. (Said once per element and reason.)`,this))}attributeChangedCallback(t,e,i){this._waitingForUrl&&i&&!this.manual&&(this._waitingForUrl=!1,this.upload())}connectedCallback(){!function(t){const e=t.constructor?.wcBindable,i=e?.inputs;if(void 0===i)return;const s=t.getAttribute;for(const e of i){const i=e.name,r="function"==typeof s?s.call(t,i.toLowerCase()):null;if(null!==r&&r.startsWith("[object ")&&_(t,i,r),!Object.prototype.hasOwnProperty.call(t,i))continue;if(!d(t,i))continue;const n=t,a=n[i];delete n[i],n[i]=a}}(this),this.style.display="none",h||(h=!0,document.addEventListener("click",u)),this._connectedCallbackPromise=this._core.observe()}disconnectedCallback(){this._core.dispose()}}var I;!function(e=customElements){e.get(t.tagNames.upload)||e.define(t.tagNames.upload,w)}(I);
|
|
2
2
|
//# sourceMappingURL=auto.min.js.map
|
package/dist/auto.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto.min.js","sources":["../src/config.ts","../src/core/operationLane.ts","../src/core/platformCapability.ts","../src/core/uploadCapabilities.ts","../src/core/UploadCore.ts","../src/autoTrigger.ts","../src/protocol/upgradeProperties.ts","../src/protocol/inputAttribute.ts","../src/components/Upload.ts","../src/bootstrapUpload.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n upload: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-uploadtarget\",\n tagNames: {\n upload: \"wcs-upload\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// `config` は内部用のライブビュー(live view)。setConfig() の更新が即座に反映される\n// 実体 `_config` をそのまま公開しており、凍結もクローンもしていない。autoTrigger /\n// components など同パッケージ内のモジュールが最新値を読むための窓口であり、\n// 「変更不可なスナップショット」が必要な外部利用には getConfig()(凍結クローンを返す)\n// を使うこと。型が readonly なのは内部からの誤書き換えを抑止するための表明にすぎない。\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\n/** A misspelt option would otherwise do nothing: `bootstrapUpload` refuses it. */\nfunction invalid(key: string): never {\n throw new Error(`[@wcstack/upload] bootstrapUpload: \"${key}\" is not one of its options, or not of the option's type.`);\n}\n\n/**\n * Applies the options given; an undefined value is left out. An option this package does not\n * have, a value of another type than its default (null, or an array for an object, included) or\n * a tag name it does not define throws, and then nothing is applied.\n */\nexport function setConfig(partialConfig: IWritableConfig): void {\n const options = _config as unknown as Record<string, unknown>;\n const tags = _config.tagNames as Record<string, string>;\n const given = Object.entries(partialConfig).filter(([, value]) => value !== undefined);\n const givenTags = Object.entries(partialConfig.tagNames ?? {}).filter(([, tag]) => tag !== undefined);\n for (const [key, value] of given) {\n const current = options[key];\n if (!Object.hasOwn(options, key) || value === null || typeof value !== typeof current || Array.isArray(value) !== Array.isArray(current)) {\n invalid(key);\n }\n }\n for (const [name, tag] of givenTags) {\n if (!Object.hasOwn(tags, name) || typeof tag !== \"string\") invalid(`tagNames.${name}`);\n }\n for (const [key, value] of given) {\n if (key !== \"tagNames\") {\n options[key] = value;\n }\n }\n for (const [name, tag] of givenTags) tags[name] = tag as string;\n frozenConfig = null;\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /io-core/operation-lane.ts by scripts/sync-io-core.mjs.\n// Run `node scripts/sync-io-core.mjs` after editing the source.\n// ===========================================================================\n\n/**\n * operationLane.ts\n *\n * Phase 4 (docs/architecture-hardening/09-remediation-design.md §5, §5.1) の\n * OperationTicket / CommitGuard / terminal CAS を型付き実装した lane プリミティブ。\n * docs/async-execution-model.md §5 が既に規範化した排他モード\n * (latest / queue / exhaust / overlap) を、`AbortController` だけでは防げない\n * 「取消不能な Promise・abort と同時に完了した結果の commit」から守るための\n * 実行時ガードとして具体化する。\n *\n * 配置方針 (§5): 本ファイルは /io-core/ の単一正典であり、scripts/sync-io-core.mjs が\n * 各 IO ノードの src/core/ へ生成コピー (AUTO-GENERATED, 編集禁止) を配布する。\n * `protocol/wcBindable.ts` と同じ copy-distribution 方式で、ランタイム依存を導入せず\n * 各パッケージのバンドルへ inline される (zero-runtime-dep / 自己完結 CDN を維持)。\n * 編集はこの正典に対して行い、`node scripts/sync-io-core.mjs` で再配布する。\n *\n * 初期 PoC は fetch の `latest` policy から開始した。現在は4 policy 全てを\n * `operationLane.test.ts` が直接検証し、生成コピーを fetch / upload / share /\n * contacts / credential / eyedropper が利用する。lane 自体は promise を実行せず、\n * bookkeeping と guard の状態機械に徹する — 実際の非同期処理は Core が駆動し\n * lane に照合する。\n */\n\n/** §5: 排他モードの語彙。async-execution-model.md §5 の 4 モードに対応 (parallel は予約語・スコープ外)。 */\nexport type LanePolicy = \"latest\" | \"queue\" | \"exhaust\" | \"overlap\";\n\n/** §5: 各 operation の一回限りの終端結果。 */\nexport type TerminalOutcome = \"success\" | \"error\" | \"timeout\" | \"aborted\" | \"stale\";\n\n/** §5: 論理操作 1 件の identity。retry は同じ operationId を再利用する。 */\nexport interface OperationTicket {\n readonly operationId: number;\n /** 発行時に捕捉した I/O Core の observe / reconnect / dispose lifecycle 世代。 */\n readonly ownerGeneration: number;\n readonly laneKey: string;\n readonly policy: LanePolicy;\n /** supersede bookkeeping に使う epoch (latest policy のみ)。 */\n readonly supersedeEpoch?: number;\n}\n\n/** §5: operation の 1 回の試行。retry で attempt++ と resource signal だけ差し替える。 */\nexport interface OperationAttempt {\n readonly operationId: number;\n readonly attempt: number;\n readonly signal?: AbortSignal;\n}\n\n/** §6: DevTools 側 channel へ流す trace(fetch では既定 off・zero-cost)。 */\nexport type OperationTraceEvent =\n | { readonly type: \"io:operation-started\"; readonly operationId: number; readonly laneKey: string; readonly policy: LanePolicy }\n | { readonly type: \"io:operation-retried\"; readonly operationId: number; readonly laneKey: string; readonly attempt: number }\n | { readonly type: \"io:operation-settled\"; readonly operationId: number; readonly laneKey: string; readonly outcome: TerminalOutcome }\n | { readonly type: \"io:stale-dropped\"; readonly operationId: number; readonly laneKey: string };\n\nexport interface OperationLaneOptions {\n /** attempt ごとに AbortController を発行し signal を渡す (fetch/upload 系)。 */\n readonly withSignal?: boolean;\n /**\n * trace subscriber。undefined なら trace record を一切生成しない\n * (§10.3 hook-off zero allocation の gate)。\n */\n readonly trace?: (event: OperationTraceEvent) => void;\n}\n\n/** 内部の終端状態。absence = pending。'committing' は multi-setter commit 中の中間状態。 */\ntype TerminalStatus = \"committing\" | TerminalOutcome;\n\n/**\n * 1 レーン = 独立した排他単位。Core が 1 つ以上所有する (module singleton にしない —\n * 複数 <wcs-fetch> 間で漏れるため)。\n */\nexport class OperationLane {\n readonly laneKey: string;\n readonly policy: LanePolicy;\n\n private _ownerGeneration = 0;\n private _latestEpoch = 0;\n private _nextOperationId = 1;\n // latest / queue / exhaust の単一 active。queue は head を指す。\n private _activeOperationId: number | undefined = undefined;\n // overlap の active set (§5: 内部 bookkeeping のみ・observable 公開はしない)。\n private readonly _activeOperationIds = new Set<number>();\n // queue policy の FIFO。\n private readonly _queue: OperationTicket[] = [];\n private _inFlightCount = 0;\n // opId → 終端状態 (absence = pending)。\n private readonly _terminal = new Map<number, TerminalStatus>();\n // claimTerminal で確定した outcome (finalize が 'committing' を最終値へ移す)。\n private readonly _claimedOutcome = new Map<number, TerminalOutcome>();\n // opId → AbortController (identity は opId が保証。cross-op clobber は構造上起きない)。\n private readonly _controllers = new Map<number, AbortController>();\n // opId → attempt 数。\n private readonly _attempts = new Map<number, number>();\n private readonly _withSignal: boolean;\n private readonly _trace?: (event: OperationTraceEvent) => void;\n\n constructor(laneKey: string, policy: LanePolicy, options: OperationLaneOptions = {}) {\n this.laneKey = laneKey;\n this.policy = policy;\n this._withSignal = options.withSignal ?? false;\n this._trace = options.trace;\n }\n\n get ownerGeneration(): number {\n return this._ownerGeneration;\n }\n\n get inFlightCount(): number {\n return this._inFlightCount;\n }\n\n get latestEpoch(): number {\n return this._latestEpoch;\n }\n\n get activeOperationId(): number | undefined {\n return this._activeOperationId;\n }\n\n /**\n * 新しい要求の到着。arrival policy を適用し ticket + 最初の attempt を発行する。\n * exhaust で実行中の場合だけ null を返す (新要求を ticket 化せず拒否 = 冪等 no-op)。\n */\n begin(): { ticket: OperationTicket; attempt: OperationAttempt } | null {\n let supersedeEpoch: number | undefined;\n switch (this.policy) {\n case \"latest\": {\n // latestEpoch を進め、旧 active を abort (可能なら)。旧 ticket は settle 時に\n // eligibility 不一致で stale となる。\n supersedeEpoch = ++this._latestEpoch;\n if (this._activeOperationId !== undefined) {\n this._abortController(this._activeOperationId);\n }\n break;\n }\n case \"exhaust\": {\n // 実行中なら新要求を拒否 (呼び出し側は既存結果へ合流)。\n if (this._activeOperationId !== undefined) {\n return null;\n }\n break;\n }\n case \"queue\":\n case \"overlap\":\n break;\n }\n\n const operationId = this._nextOperationId++;\n const ticket: OperationTicket = {\n operationId,\n ownerGeneration: this._ownerGeneration,\n laneKey: this.laneKey,\n policy: this.policy,\n supersedeEpoch,\n };\n\n switch (this.policy) {\n case \"latest\":\n case \"exhaust\":\n this._activeOperationId = operationId;\n break;\n case \"queue\":\n this._queue.push(ticket);\n // 先頭だけを active にする (先行が完了するまで待つ)。\n if (this._activeOperationId === undefined) {\n this._activeOperationId = operationId;\n }\n break;\n case \"overlap\":\n this._activeOperationIds.add(operationId);\n break;\n }\n\n this._inFlightCount += 1;\n this._attempts.set(operationId, 1);\n const attempt = this._makeAttempt(operationId, 1);\n if (this._trace !== undefined) {\n this._trace({ type: \"io:operation-started\", operationId, laneKey: this.laneKey, policy: this.policy });\n }\n return { ticket, attempt };\n }\n\n /**\n * retry: 同じ operationId に新しい attempt を作る。attempt number と resource signal\n * だけを更新する (§5)。既に終端した operation には作れない (null)。\n */\n retry(ticket: OperationTicket): OperationAttempt | null {\n if (ticket.ownerGeneration !== this._ownerGeneration) return null;\n if (this._terminal.has(ticket.operationId)) return null;\n const previous = this._attempts.get(ticket.operationId);\n if (previous === undefined) return null;\n const attemptNo = previous + 1;\n this._attempts.set(ticket.operationId, attemptNo);\n // 前の attempt の signal は破棄し、新しい controller を張る。\n this._releaseController(ticket.operationId);\n const attempt = this._makeAttempt(ticket.operationId, attemptNo);\n if (this._trace !== undefined) {\n this._trace({ type: \"io:operation-retried\", operationId: ticket.operationId, laneKey: this.laneKey, attempt: attemptNo });\n }\n return attempt;\n }\n\n /**\n * CommitGuard (§5.1)。外部可視の setter / event dispatch の直前に呼ぶ。\n * (1) owner lifecycle generation 一致 (2) terminal settle 前 (3) policy eligibility。\n */\n canCommit(ticket: OperationTicket): boolean {\n if (ticket.ownerGeneration !== this._ownerGeneration) return false;\n const status = this._terminal.get(ticket.operationId);\n // absence = pending / 'committing' = multi-setter commit 中。どちらも settle 前。\n if (status !== undefined && status !== \"committing\") return false;\n return this._isEligible(ticket);\n }\n\n /**\n * terminal CAS (§5.1): pending → committing を claim する。勝者だけが true。\n * eligibility / owner gen を満たさない場合も false。claim 後は commit 中となり、\n * canCommit は各 setter の直前で再検査する (setter が同期 supersede しても取りこぼさない)。\n */\n claimTerminal(ticket: OperationTicket, outcome: TerminalOutcome): boolean {\n if (ticket.ownerGeneration !== this._ownerGeneration) return false;\n if (this._terminal.has(ticket.operationId)) return false; // 既に committing / 終端\n if (!this._isEligible(ticket)) return false;\n this._terminal.set(ticket.operationId, \"committing\");\n this._claimedOutcome.set(ticket.operationId, outcome);\n return true;\n }\n\n /** claim 済み outcome (timer が claim → catch が読む等)。未 claim なら undefined。 */\n claimedOutcome(ticket: OperationTicket): TerminalOutcome | undefined {\n return this._claimedOutcome.get(ticket.operationId);\n }\n\n /**\n * operation の後始末。claim 済みなら outcome を確定し、未 claim なら stale-drop。\n * controller を解放し in-flight を減らし、policy の bookkeeping を進める。冪等。\n */\n finalize(ticket: OperationTicket): void {\n const operationId = ticket.operationId;\n const status = this._terminal.get(operationId);\n if (status !== undefined && status !== \"committing\") {\n // 既に確定済み。冪等に return。\n return;\n }\n let outcome: TerminalOutcome;\n if (status === \"committing\") {\n outcome = this._claimedOutcome.get(operationId) ?? \"stale\";\n } else {\n // 一度も claim されなかった (supersede / dispose で eligibility を失った)。\n outcome = \"stale\";\n }\n this._terminal.set(operationId, outcome);\n this._claimedOutcome.delete(operationId);\n this._releaseController(operationId);\n this._attempts.delete(operationId);\n if (this._inFlightCount > 0) this._inFlightCount -= 1;\n this._advanceBookkeeping(operationId);\n if (this._trace !== undefined) {\n if (outcome === \"stale\") {\n this._trace({ type: \"io:stale-dropped\", operationId, laneKey: this.laneKey });\n } else {\n this._trace({ type: \"io:operation-settled\", operationId, laneKey: this.laneKey, outcome });\n }\n }\n }\n\n /** operation の signal (resource 解放用)。withSignal でなければ undefined。 */\n signalOf(ticket: OperationTicket): AbortSignal | undefined {\n return this._controllers.get(ticket.operationId)?.signal;\n }\n\n /** best-effort な resource 中断。正しさは owner gen / eligibility / terminal CAS が担う。 */\n abort(ticket: OperationTicket): void {\n this._abortController(ticket.operationId);\n }\n\n /**\n * 現在 active な operation を中断する (利用者による明示キャンセル)。epoch は進めない —\n * 中断された operation は eligibility を保ったまま 'aborted' を claim できる\n * (loading をクリアしつつ in-flight 状態を残す)。\n */\n abortActive(): void {\n if (this._activeOperationId !== undefined) {\n this._abortController(this._activeOperationId);\n }\n for (const operationId of this._activeOperationIds) {\n this._abortController(operationId);\n }\n }\n\n /**\n * dispose (§4.1 world generation)。owner generation を bump して全 ticket を無効化し、\n * 生きている controller を全て abort する。dispose 後に settle した operation は\n * owner gen 不一致で外部 commit しない。retention gate (§10.3) のため live な\n * 全 operation を即時に stale として finalize し、controller / attempt を解放する。\n */\n disposeOwner(): void {\n this._ownerGeneration += 1;\n for (const operationId of Array.from(this._controllers.keys())) {\n this._abortController(operationId);\n // finalize は dispose 後 (terminal='stale') に early-return するため controller を\n // 解放しない。retention gate (§10.3) を満たすためここで明示的に解放する。\n this._releaseController(operationId);\n }\n for (const operationId of Array.from(this._attempts.keys())) {\n if (!this._terminal.has(operationId)) {\n this._terminal.set(operationId, \"stale\");\n }\n this._claimedOutcome.delete(operationId);\n this._attempts.delete(operationId);\n if (this._trace !== undefined) {\n this._trace({ type: \"io:stale-dropped\", operationId, laneKey: this.laneKey });\n }\n }\n this._activeOperationId = undefined;\n this._activeOperationIds.clear();\n this._queue.length = 0;\n this._inFlightCount = 0;\n }\n\n // --- internal ---\n\n private _makeAttempt(operationId: number, attemptNo: number): OperationAttempt {\n let signal: AbortSignal | undefined;\n // AbortController 不在環境(古い runtime / 一部 SSR)では degraded: signal なしで進む。\n // 正しさは owner generation / eligibility / terminal CAS が担うため、native 中断が\n // 無くても supersede / dispose は機能する(best-effort resource 中断が省かれるだけ)。\n if (this._withSignal && typeof AbortController === \"function\") {\n const controller = new AbortController();\n this._controllers.set(operationId, controller);\n signal = controller.signal;\n }\n return { operationId, attempt: attemptNo, signal };\n }\n\n private _isEligible(ticket: OperationTicket): boolean {\n switch (this.policy) {\n case \"latest\":\n return ticket.supersedeEpoch === this._latestEpoch;\n case \"queue\":\n case \"exhaust\":\n return this._activeOperationId === ticket.operationId;\n case \"overlap\":\n return this._activeOperationIds.has(ticket.operationId);\n }\n }\n\n private _advanceBookkeeping(operationId: number): void {\n switch (this.policy) {\n case \"latest\":\n case \"exhaust\":\n if (this._activeOperationId === operationId) {\n this._activeOperationId = undefined;\n }\n break;\n case \"queue\": {\n // 完了した ticket を FIFO から取り除き、次の先頭を active にする。filter で\n // 「先頭 / 非先頭 / 不在」を一様に扱う (finalize は冪等ガードを通った op のみ到達)。\n const remaining = this._queue.filter((t) => t.operationId !== operationId);\n this._queue.length = 0;\n this._queue.push(...remaining);\n this._activeOperationId = this._queue.length > 0 ? this._queue[0].operationId : undefined;\n break;\n }\n case \"overlap\":\n this._activeOperationIds.delete(operationId);\n break;\n }\n }\n\n private _abortController(operationId: number): void {\n const controller = this._controllers.get(operationId);\n if (controller !== undefined && !controller.signal.aborted) {\n controller.abort();\n }\n }\n\n private _releaseController(operationId: number): void {\n this._controllers.delete(operationId);\n }\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /io-core/platform-capability.ts by scripts/sync-io-core.mjs.\n// Run `node scripts/sync-io-core.mjs` after editing the source.\n// ===========================================================================\n\n/**\n * platform-capability.ts\n *\n * Phase 6(docs/architecture-hardening/09-remediation-design.md §7.2 /\n * 07-browser-capability-variance.md)の browser capability 判定と error taxonomy の\n * 汎用プリミティブ。node 固有の capability registry / error code は各パッケージが\n * 別ファイルで宣言し、この汎用層(型 + assess 機構)を import する。\n *\n * 原則:\n * - feature detection は境界(利用直前)で行う。module 評価時に browser global を\n * 参照しない(SSR / worker で import が失敗しない)。\n * - capability ID(`web.fetch` 等)は文字列を global property path として eval せず、\n * registry が ID ごとに副作用のない presence probe を対応付ける。\n * - availability / permission / readiness / activity / operation error を 1 つの\n * `ready / unsupported / error` enum に畳まない。required 欠如は開始しない、\n * optional 欠如は宣言済み fallback で readiness を `degraded` にする。\n *\n * 配置: 本ファイルは /io-core/ の単一正典であり、scripts/sync-io-core.mjs が\n * 各 IO ノードの src/core/ へ生成コピー (AUTO-GENERATED, 編集禁止) を配布する。\n * `protocol/wcBindable.ts` と同じ copy-distribution 方式で、ランタイム依存を導入せず\n * 各パッケージのバンドルへ inline される (zero-runtime-dep / 自己完結 CDN を維持)。\n * 編集はこの正典に対して行い、`node scripts/sync-io-core.mjs` で再配布する。\n *\n * pure(module 評価時に browser global 非参照)。\n */\n\nexport type Availability = \"available\" | \"missing\" | \"unknown\";\nexport type PermissionState = \"granted\" | \"denied\" | \"prompt\" | \"not-applicable\" | \"unknown\";\nexport type Readiness = \"idle\" | \"ready\" | \"degraded\";\nexport type Activity = \"inactive\" | \"active\";\nexport type PreconditionState = \"satisfied\" | \"required\" | \"not-applicable\";\n\n/** operation error の phase(taxonomy)。 */\nexport type WcsIoErrorPhase = \"probe\" | \"start\" | \"execute\" | \"decode\" | \"commit\" | \"dispose\";\n\n/** serializable な error info(non-cloneable な cause とは分離。DevTools / remote へは info のみ)。 */\nexport interface WcsIoErrorInfo {\n readonly code: string;\n readonly phase: WcsIoErrorPhase;\n readonly recoverable: boolean;\n readonly capabilityId?: string;\n readonly message: string;\n}\n\nexport interface PlatformAssessment {\n readonly availability: ReadonlyMap<string, Availability>;\n readonly permission: PermissionState;\n readonly readiness: Readiness;\n readonly activity: Activity;\n readonly preconditions: {\n readonly secureContext: PreconditionState;\n readonly userActivation: PreconditionState;\n };\n readonly epoch: number;\n readonly lastError?: WcsIoErrorInfo;\n}\n\n/** capability 1 件の仕様。probe は副作用なく presence を返す(利用直前に呼ぶ)。 */\nexport interface CapabilitySpec {\n readonly probe: () => boolean;\n readonly requiresSecureContext?: boolean;\n readonly requiresUserActivation?: boolean;\n /** browser compatibility dataset のキー(任意・診断用)。 */\n readonly compatKey?: string;\n}\n\nexport type CapabilityRegistry = ReadonlyMap<string, CapabilitySpec>;\n\nexport interface AssessOptions {\n readonly required: readonly string[];\n readonly optional?: readonly string[];\n readonly permission?: PermissionState;\n readonly activity?: Activity;\n readonly epoch?: number;\n readonly lastError?: WcsIoErrorInfo;\n}\n\nfunction isSecureContext(): boolean {\n return (globalThis as { isSecureContext?: unknown }).isSecureContext === true;\n}\n\n/**\n * capability を利用直前に評価して PlatformAssessment を作る。\n * required が 1 つでも欠ければ readiness は \"idle\"(開始不可)、\n * required 揃い + optional 欠けは \"degraded\"、全揃いは \"ready\"。\n */\nexport function assessCapabilities(registry: CapabilityRegistry, options: AssessOptions): PlatformAssessment {\n const availability = new Map<string, Availability>();\n const evaluate = (id: string): Availability => {\n const spec = registry.get(id);\n if (spec === undefined) return \"unknown\";\n return spec.probe() ? \"available\" : \"missing\";\n };\n\n let requiredAllAvailable = true;\n for (const id of options.required) {\n const a = evaluate(id);\n availability.set(id, a);\n if (a !== \"available\") requiredAllAvailable = false;\n }\n let optionalAllAvailable = true;\n for (const id of options.optional ?? []) {\n const a = evaluate(id);\n availability.set(id, a);\n if (a !== \"available\") optionalAllAvailable = false;\n }\n\n const readiness: Readiness = !requiredAllAvailable ? \"idle\" : (optionalAllAvailable ? \"ready\" : \"degraded\");\n\n // preconditions: 対象 capability のいずれかが要求する場合だけ評価する。\n const allIds = [...options.required, ...(options.optional ?? [])];\n const needsSecure = allIds.some((id) => registry.get(id)?.requiresSecureContext === true);\n const needsActivation = allIds.some((id) => registry.get(id)?.requiresUserActivation === true);\n const secureContext: PreconditionState = needsSecure ? (isSecureContext() ? \"satisfied\" : \"required\") : \"not-applicable\";\n const userActivation: PreconditionState = needsActivation ? \"required\" : \"not-applicable\";\n\n return {\n availability,\n permission: options.permission ?? \"not-applicable\",\n readiness,\n activity: options.activity ?? \"inactive\",\n preconditions: { secureContext, userActivation },\n epoch: options.epoch ?? 0,\n lastError: options.lastError,\n };\n}\n\n/** availability から「required がすべて available か」を判定するヘルパ(supported の最低条件)。 */\nexport function requiredCapabilitiesAvailable(assessment: PlatformAssessment, required: readonly string[]): boolean {\n return required.every((id) => assessment.availability.get(id) === \"available\");\n}\n\n/**\n * このページで機能が使えない理由(使える、または分からないなら null)。利用直前に読む。\n *\n * - `\"insecure-context\"`: 安全なコンテキストではない(`isSecureContext === false`)。\n * Permissions API が扱う機能はどれも安全なコンテキストを要る。\n * - `\"policy-blocked\"`: Permissions-Policy(サーバーのヘッダ、または `allow` の無い\n * `<iframe>`)がその機能を切っている。\n *\n * どちらも Permissions API は教えない: Chromium はポリシーで切られた文書でも\n * `granted` を、安全でない origin では `denied` を返す。利用者の拒否と区別するため、\n * 見張り役(`<wcs-permission>`)も取りに行く側も `unsupported` を報告する\n * (docs/v4-direction-2026-10.md の決定、state-field-report)。\n * `isSecureContext` が無い環境(SSR・テスト)は判断しない。\n */\nexport type FeatureUnavailableReason = \"insecure-context\" | \"policy-blocked\";\n\n/** Permissions-Policy が制御する機能(permission 名と同じ文字列)。 */\nconst POLICY_CONTROLLED = new Set([\n \"camera\", \"microphone\", \"geolocation\", \"midi\", \"clipboard-read\", \"clipboard-write\",\n \"screen-wake-lock\", \"idle-detection\", \"accelerometer\", \"gyroscope\", \"magnetometer\",\n \"ambient-light-sensor\", \"display-capture\",\n]);\n\ninterface PolicyLike { allowsFeature(feature: string): boolean }\n\nexport function featureUnavailable(feature: string): FeatureUnavailableReason | null {\n const g = globalThis as { isSecureContext?: unknown; document?: { permissionsPolicy?: PolicyLike; featurePolicy?: PolicyLike } };\n if (g.isSecureContext === false) return \"insecure-context\";\n if (!POLICY_CONTROLLED.has(feature)) return null;\n const policy = g.document?.permissionsPolicy ?? g.document?.featurePolicy;\n if (policy === undefined || typeof policy.allowsFeature !== \"function\") return null;\n try {\n return policy.allowsFeature(feature) ? null : \"policy-blocked\";\n } catch {\n return null;\n }\n}\n\n/** `featureUnavailable` の理由を、作者が直し方を読める文にする。`what` は文頭(「The camera」など)。 */\nexport function featureUnavailableMessage(what: string, feature: string, reason: FeatureUnavailableReason): string {\n return reason === \"insecure-context\"\n ? `${what} needs a secure context (https:, or http://localhost), and this page is not one.`\n : `${what} is turned off for this page by a Permissions-Policy: the server's Permissions-Policy header, ` +\n `or an <iframe> without allow=\"${feature}\". The browser's site settings cannot change that.`;\n}\n","/**\n * uploadCapabilities.ts\n *\n * Upload node 固有の capability registry と error code。汎用の assess 機構・型は\n * `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から\n * import する。node 固有の宣言はこのハンドライトファイルに置き、生成コピーとは分離する。\n */\n\nimport { CapabilityRegistry, CapabilitySpec } from \"./platformCapability.js\";\n\n/** 安定した upload error code(taxonomy)。値は公開キーとして固定。 */\nexport const WCS_UPLOAD_ERROR_CODE = {\n CapabilityMissing: \"capability-missing\",\n InvalidArgument: \"invalid-argument\",\n Network: \"network\",\n HttpError: \"http-error\",\n} as const;\n\n/**\n * upload node の capability registry。`XMLHttpRequest`(progress 取得のため fetch では\n * なく XHR を用いる)の presence を probe する。\n */\nexport const UPLOAD_CAPABILITIES: CapabilityRegistry = new Map<string, CapabilitySpec>([\n [\"web.xhr\", { probe: () => typeof (globalThis as { XMLHttpRequest?: unknown }).XMLHttpRequest === \"function\", compatKey: \"api.XMLHttpRequest\" }],\n]);\n","import { IWcBindable } from \"../types.js\";\nimport { OperationLane, OperationTicket } from \"./operationLane.js\";\nimport {\n PlatformAssessment,\n WcsIoErrorInfo,\n WcsIoErrorPhase,\n assessCapabilities,\n requiredCapabilitiesAvailable,\n} from \"./platformCapability.js\";\nimport { UPLOAD_CAPABILITIES, WCS_UPLOAD_ERROR_CODE } from \"./uploadCapabilities.js\";\n\nexport interface UploadRequestOptions {\n method?: string;\n headers?: Record<string, string>;\n fieldName?: string;\n}\n\nexport class UploadCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-upload:response\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-upload:loading-changed\", semantics: \"state\" },\n { name: \"progress\", event: \"wcs-upload:progress\", semantics: \"state\" },\n { name: \"error\", event: \"wcs-upload:error\", semantics: \"state\" },\n { name: \"status\", event: \"wcs-upload:response\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.status },\n // Serializable failure taxonomy (stable code / phase / recoverable), or null.\n // Additive bindable output; the existing `error` property/event are unchanged.\n // Fires its own `wcs-upload:error-info-changed` event; no getter, so the bound\n // value is the event detail (mirrors `error` / `loading`). An abort() is not a\n // failure — it clears loading without setting error/errorInfo.\n { name: \"errorInfo\", event: \"wcs-upload:error-info-changed\", semantics: \"state\" },\n ],\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n ],\n commands: [\n { name: \"upload\", async: true },\n { name: \"abort\" },\n ],\n };\n\n // Required capability (probed at call time, never at module eval).\n private static readonly REQUIRED_CAPABILITIES = [\"web.xhr\"] as const;\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _progress: number = 0;\n private _error: any = null;\n private _status: number = 0;\n private _errorInfo: WcsIoErrorInfo | null = null;\n private _xhr: XMLHttpRequest | null = null;\n private _promise: Promise<any> = Promise.resolve(null);\n // Concurrency lane (io-core). `latest`: a new upload supersedes the in-flight one\n // (switchMap). `withSignal: false`: upload uses XMLHttpRequest.abort() rather than\n // an AbortSignal, so the lane owns epoch / commit-guard while abort() below owns\n // the XHR cancellation. dispose() bumps the owner generation and aborts the XHR.\n private _lane = new OperationLane(\"upload\", \"latest\", { withSignal: false });\n // SSR: no asynchronous probe to await, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). Upload is command-driven with no subscription to establish,\n // so observe() is an idempotent no-op that resolves once ready; dispose() bumps\n // the lane's owner generation (invalidating any in-flight upload) and aborts the\n // XHR.\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._lane.disposeOwner();\n this.abort();\n // The aborted upload's handler can no longer claim its end (the owner generation\n // moved), so it is published here (timing-and-firing-contract §22): a route the\n // element leaves keeps its nodes — bindings included — for the next entry, and\n // state would keep `loading`. `progress` stays where the transfer stopped, as on\n // any abort. (`loading-changed` is not same-value guarded: only a change is sent.)\n if (this._loading) this._setLoading(false);\n }\n\n get value(): any {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get progress(): number {\n return this._progress;\n }\n\n get error(): any {\n return this._error;\n }\n\n get status(): number {\n return this._status;\n }\n\n get promise(): Promise<any> {\n return this._promise;\n }\n\n /**\n * The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /\n * `recoverable` / `capabilityId`), or null. Exposed as an additive wc-bindable\n * property (event `wcs-upload:error-info-changed`); the existing `error`\n * property/event are unchanged. An abort() is not a failure (no errorInfo).\n */\n get errorInfo(): WcsIoErrorInfo | null {\n return this._errorInfo;\n }\n\n /**\n * Whether the required platform capability (`web.xhr`) is available right now —\n * decided by call-time feature detection, not User-Agent. Core-only, additive.\n */\n get supported(): boolean {\n return requiredCapabilitiesAvailable(this.platformAssessment, UploadCore.REQUIRED_CAPABILITIES);\n }\n\n /**\n * Full platform assessment (availability / readiness / preconditions), probed at\n * call time. Core-only opt-in dev / sidecar view.\n */\n get platformAssessment(): PlatformAssessment {\n return assessCapabilities(UPLOAD_CAPABILITIES, {\n required: UploadCore.REQUIRED_CAPABILITIES,\n activity: this._loading ? \"active\" : \"inactive\",\n lastError: this._errorInfo ?? undefined,\n });\n }\n\n // CommitGuard (§5.1): external setters / event dispatch only run if the ticket\n // still holds owner generation, is pre-terminal, and is the lane's latest epoch\n // (a superseding upload can invalidate a ticket mid-commit).\n private _commitStep(ticket: OperationTicket, step: () => void): void {\n if (this._lane.canCommit(ticket)) {\n step();\n }\n }\n\n // --- State setters with event dispatch ---\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setProgress(progress: number): void {\n this._progress = progress;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\n detail: progress,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n // Same-value guard (async-io-node-guidelines.md §3.3). `error` is state-ish,\n // so suppressing redundant null→null dispatches (every upload start clears a\n // usually-already-null error) avoids a spurious wcs-upload:error per\n // successful upload. Reference identity is sufficient: each failure builds a\n // fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Surface a Shell-originated error (e.g. maxSize / accept validation, which the\n // Core has no knowledge of) on the shared `error` property so `el.error` stays\n // sticky and consistent with Core-originated errors — same error contract as the\n // rest of the @wcstack IO nodes. A later successful upload() clears it via\n // _setError(null). Dispatches wcs-upload:error like any other error transition.\n setError(error: any): void {\n this._setError(error);\n }\n\n private _setResponse(value: any, status: number): void {\n this._value = value;\n this._status = status;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\n detail: { value, status },\n bubbles: true,\n }));\n }\n\n // Single mutation point for `errorInfo`, mirroring `_setError`'s same-value guard\n // and event dispatch so the additive `errorInfo` wc-bindable property stays in\n // sync with `error`. Each failure builds a fresh object (reference guard passes);\n // the clear path passes null (suppresses a redundant null→null per upload start).\n private _setErrorInfo(code: string, phase: WcsIoErrorPhase, recoverable: boolean, message: string, capabilityId?: string): void {\n this._commitErrorInfo({ code, phase, recoverable, message, ...(capabilityId === undefined ? {} : { capabilityId }) });\n }\n\n private _commitErrorInfo(info: WcsIoErrorInfo | null): void {\n if (this._errorInfo === info) return;\n this._errorInfo = info;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error-info-changed\", {\n detail: info,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n abort(): void {\n // Abort the current XHR. Its `abort` event handler claims the `aborted` terminal\n // (while the ticket is still latest — abort() runs before a superseding upload's\n // begin()), unifying the loading-release path with success/error/network. When a\n // superseding upload or dispose() has already advanced the epoch/owner gen, the\n // handler's claim fails and it writes nothing (stale-drop).\n if (this._xhr) {\n this._xhr.abort();\n this._xhr = null;\n }\n }\n\n async upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\n // never-throw: 引数バリデーション失敗は例外ではなく error プロパティに流し、\n // サニタイズ値(null)を返す。command-token 経路からの呼び出しが unhandled\n // rejection にならず、「upload() は全終了ケースで resolve」契約とも整合する。\n if (!url) {\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.InvalidArgument, \"start\", false, \"url is required.\");\n this._setError({ message: \"url is required.\" });\n return null;\n }\n if (!files || files.length === 0) {\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.InvalidArgument, \"start\", false, \"files are required.\");\n this._setError({ message: \"files are required.\" });\n return null;\n }\n\n const p = this._doUpload(url, files, options);\n this._promise = p;\n return p;\n }\n\n // --- Internal ---\n\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\n // Probe the required capability just before starting (SSR / very old runtime).\n const assessment = this.platformAssessment;\n if (!requiredCapabilitiesAvailable(assessment, UploadCore.REQUIRED_CAPABILITIES)) {\n const missing = UploadCore.REQUIRED_CAPABILITIES.find((id) => assessment.availability.get(id) !== \"available\");\n const message = `Required capability \"${missing}\" is unavailable.`;\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.CapabilityMissing, \"start\", false, message, missing);\n this._setError({ message });\n return Promise.resolve(null);\n }\n\n // Abort the previous XHR BEFORE advancing the epoch, so its `abort` handler\n // claims `aborted` while still latest (preserving the loading true→false→true\n // supersede sequence). Then begin() advances the epoch for THIS upload.\n this.abort();\n const started = this._lane.begin()!; // `latest` begin never returns null\n const { ticket } = started;\n\n this._commitStep(ticket, () => this._setLoading(true));\n this._commitStep(ticket, () => {\n this._setProgress(0);\n this._commitErrorInfo(null);\n this._setError(null);\n });\n\n const {\n method = \"POST\",\n headers = {},\n fieldName = \"file\",\n } = options;\n\n const formData = new FormData();\n for (let i = 0; i < files.length; i++) {\n formData.append(fieldName, files[i]);\n }\n\n return new Promise<any>((resolve) => {\n const xhr = new XMLHttpRequest();\n this._xhr = xhr;\n\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\n // Guarded: a superseded / disposed upload's late progress writes nothing.\n this._commitStep(ticket, () => {\n if (event.lengthComputable) {\n this._setProgress(Math.round((event.loaded / event.total) * 100));\n }\n });\n });\n\n xhr.addEventListener(\"load\", () => {\n this._xhr = null;\n if (xhr.status >= 200 && xhr.status < 300) {\n if (!this._lane.claimTerminal(ticket, \"success\")) { resolve(null); this._lane.finalize(ticket); return; }\n let value: any = xhr.responseText;\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n try { value = JSON.parse(xhr.responseText); } catch { /* テキストのまま */ }\n }\n this._commitStep(ticket, () => this._setProgress(100));\n this._commitStep(ticket, () => this._setResponse(value, xhr.status));\n this._commitStep(ticket, () => this._setLoading(false));\n this._lane.finalize(ticket);\n resolve(value);\n } else {\n if (!this._lane.claimTerminal(ticket, \"error\")) { resolve(null); this._lane.finalize(ticket); return; }\n const error = { status: xhr.status, statusText: xhr.statusText, body: xhr.responseText };\n this._commitStep(ticket, () => {\n this._status = xhr.status; // HTTP error keeps status (no wcs-upload:response — value not reset)\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.HttpError, \"execute\", true, `HTTP ${xhr.status} ${xhr.statusText}`);\n this._setError(error);\n });\n this._commitStep(ticket, () => this._setLoading(false));\n this._lane.finalize(ticket);\n resolve(null);\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n this._xhr = null;\n if (!this._lane.claimTerminal(ticket, \"error\")) { resolve(null); this._lane.finalize(ticket); return; }\n const message = \"Network error\";\n this._commitStep(ticket, () => {\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.Network, \"execute\", true, message);\n this._setError({ message });\n });\n this._commitStep(ticket, () => this._setLoading(false));\n this._lane.finalize(ticket);\n resolve(null);\n });\n\n xhr.addEventListener(\"abort\", () => {\n this._xhr = null;\n // abort is a routine cancellation, not a failure: claim the `aborted`\n // terminal and clear loading only (no error/errorInfo). A superseded /\n // disposed ticket fails the claim and drops.\n if (this._lane.claimTerminal(ticket, \"aborted\")) {\n this._commitStep(ticket, () => this._setLoading(false));\n }\n this._lane.finalize(ticket);\n resolve(null);\n });\n\n xhr.open(method, url);\n\n for (const [name, value] of Object.entries(headers)) {\n xhr.setRequestHeader(name, value);\n }\n\n xhr.send(formData);\n });\n }\n}\n","import { config } from \"./config.js\";\nimport type { WcsUpload } from \"./components/Upload.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\n if (!uploadId) return;\n\n // Resolve the registered constructor at call time instead of importing WcsUpload\n // as a value. The value import created a components/Upload.ts ⇄ autoTrigger.ts\n // cycle (WcsUpload.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-upload> class matches — without the import cycle.\n const UploadCtor = customElements.get(config.tagNames.upload);\n const el = document.getElementById(uploadId);\n if (!UploadCtor || !(el instanceof UploadCtor)) return;\n const uploadElement = el as WcsUpload;\n\n // ファイルと URL が揃っている場合のみ既定動作を抑止\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\n event.preventDefault();\n }\n uploadElement.upload();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/upgrade-properties.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// custom element の property upgrade — `static wcBindable.inputs` に宣言した入力のうち、\n// 要素が upgrade される前に代入された own データプロパティを取り込み直す。\n//\n// なぜ必要か:\n// 未定義タグの要素は素の HTMLElement なので、`el.url = \"...\"` は own データプロパティを作る。\n// upgrade 後にクラスの accessor が prototype へ入っても own プロパティが優先されるため、\n// setter は二度と呼ばれず、値は要素へ届かないまま消える(エラーも警告も出ない)。\n// 常にプロパティ代入を行う framework(Angular の `[prop]`、Lit の `.prop=`、\n// Solid の `prop:`、Vue の `.prop` 修飾子)× 遅延定義(autoloader / CDN / code-split)で\n// 常態的に起きる。docs/architecture-hardening/13-framework-adapter-binding-constraints.md §1.2。\n//\n// 安全側の判定:\n// own プロパティがあっても、prototype チェーンに accessor が無ければ「シャドウ」ではなく\n// その own プロパティ自体が正規の格納先なので触らない(public class field を壊さない)。\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/upgrade-properties.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/upgradeProperties.ts). Those copies are generated — do not edit them.\nimport { IWcBindable } from \"./wcBindable.js\";\n\nfunction hasAccessorOnPrototype(target: object, name: string): boolean {\n let proto = Object.getPrototypeOf(target);\n while (proto !== null) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, name);\n if (descriptor !== undefined) {\n return typeof descriptor.get === \"function\" || typeof descriptor.set === \"function\";\n }\n proto = Object.getPrototypeOf(proto);\n }\n return false;\n}\n\n/**\n * `connectedCallback` の先頭で呼ぶ。宣言済み input のうち upgrade 前の代入で\n * accessor をシャドウしている own プロパティを、delete → 再代入で setter に通し直す。\n *\n * - 冪等: 再代入は accessor を通るので own プロパティは残らず、2 回目以降は no-op。\n * - 宣言に `inputs` が無い要素、`wcBindable` を持たない要素では何もしない。\n * - 値の意味は変えない。今まで捨てられていた代入が届くようになる一方向の変化。\n */\nexport function upgradeProperties(element: object): void {\n const declaration = (element as { constructor?: { wcBindable?: IWcBindable } }).constructor?.wcBindable;\n const inputs = declaration?.inputs;\n if (inputs === undefined) return;\n for (const input of inputs) {\n const name = input.name;\n if (!Object.prototype.hasOwnProperty.call(element, name)) continue;\n if (!hasAccessorOnPrototype(element, name)) continue;\n const record = element as Record<string, unknown>;\n const value = record[name];\n delete record[name];\n record[name] = value;\n }\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/input-attribute.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// 属性へ反映する wc-bindable 入力の producer 側(SPEC-extensions § Producer guidance for inputs の P1〜P3)。\n// 入力の setter は属性をこの 2 関数で書く。それで次が揃う:\n// - `undefined` は「値が無い」(P1): 属性を、この関数で最初に書く前の状態 — マークアップに書かれた値、\n// 無ければ属性なし(= その入力の文書化した既定値)— へ戻す。applier プロファイルを宣言する binder は\n// 値の後の `undefined` を書き(A2)、React 19 も書き、直接の代入でも届く。\n// - `null` はクリア(P2): 属性なし、つまり文書化した既定値。\n// - どちらも文字列 \"undefined\" / \"null\" として属性に入らない。\n//\n// 「最初に書く前」は、その最初の書き込みのときに読む(遅延)。upgrade 前に代入されたプロパティは\n// connectedCallback の upgradeProperties() が通し直すので、そのときにはパーサが書いた属性が揃っている。\n// 要素自身が setter を通さずに書いた属性は、最初の書き込みより前なら「最初の状態」に含まれる。\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/input-attribute.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/inputAttribute.ts). Those copies are generated — do not edit them.\n\nconst initialAttributes = new WeakMap<Element, Map<string, string | null>>();\n\n/** The attribute as it stood before the first write through these helpers. */\nfunction initialAttribute(el: Element, name: string): string | null {\n let byName = initialAttributes.get(el);\n if (byName === undefined) {\n byName = new Map();\n initialAttributes.set(el, byName);\n }\n if (!byName.has(name)) byName.set(name, el.getAttribute(name));\n return byName.get(name) as string | null;\n}\n\nfunction writeAttribute(el: Element, name: string, value: string | null): void {\n if (value === null) el.removeAttribute(name);\n else el.setAttribute(name, value);\n}\n\n/**\n * A value attribute. `value` is written as `String(value)`; `null` removes the attribute;\n * `undefined` restores the attribute the element started with.\n */\nexport function reflectAttribute(el: Element, name: string, value: unknown): void {\n const initial = initialAttribute(el, name);\n writeAttribute(el, name, value === undefined ? initial : value === null ? null : String(value));\n}\n\n/**\n * A boolean attribute, present while `value` is truthy (`null` and `false` remove it);\n * `undefined` restores the attribute the element started with.\n */\nexport function reflectBooleanAttribute(el: Element, name: string, value: unknown): void {\n const initial = initialAttribute(el, name);\n writeAttribute(el, name, value === undefined ? initial : value ? \"\" : null);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\nimport { UploadCore } from \"../core/UploadCore.js\";\nimport { WcsIoErrorInfo } from \"../core/platformCapability.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\nimport { upgradeProperties } from \"../protocol/upgradeProperties.js\";\nimport { reflectAttribute, reflectBooleanAttribute } from \"../protocol/inputAttribute.js\";\n\nexport class WcsUpload extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...UploadCore.wcBindable,\n properties: [\n ...UploadCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\", semantics: \"state\" },\n { name: \"files\", event: \"wcs-upload:files-changed\", semantics: \"state\" },\n ],\n // Shell-level input surface. The Core declares only the portable `url` / `method` /\n // `fieldName`; the Shell adds the DOM-driven settable surface. No `attribute` hints\n // are given: the `url` / `method` / `fieldName` / `multiple` / `maxSize` / `accept` /\n // `manual` setters reflect to their attributes themselves, and a binding system that\n // mirrored inputs[].attribute (@wcstack/state 3.x) would set the attribute twice\n // (`files` / `trigger` are not attribute-backed). `commands` (upload / abort) are inherited unchanged from the\n // Core via the spread above.\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n { name: \"multiple\" },\n { name: \"maxSize\" },\n { name: \"accept\" },\n { name: \"manual\" },\n { name: \"files\" },\n { name: \"trigger\" },\n ],\n };\n // `url` を観測するのは FetchCore のシェルと構造を揃えるためだが、upload は\n // url 変更だけでは送信できない(files が必須)。そのため attributeChangedCallback は\n // 意図的に何もしない。url 変更で自動送信しないことは仕様であり、テストで担保している。\n static get observedAttributes(): string[] { return [\"url\"]; }\n\n private _core: UploadCore;\n private _files: FileList | File[] | null = null;\n private _trigger: boolean = false;\n // The reasons `[wcs/command-not-ready]` was said for, once each per element\n // (docs/v4-direction-2026-10.md §5.1, the I/O command policy).\n private _told: Set<string> | null = null;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new UploadCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-upload:loading-changed\": (d) => ({ loading: d === true }),\n \"wcs-upload:error\": (d) => ({ error: d != null }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n //\n // setter は null / undefined を setAttribute に文字列化させない(\"undefined\" の url へ\n // 送信したり、\"null\" の method を使ったりしないため)。`null` は属性を外して既定値に戻し、\n // `undefined` は要素が最初に持っていた属性へ戻す(wc-bindable producer guidance P1。\n // React 19 や直接の代入は undefined を書く。@wcstack/state は書かない)。\n\n get url(): string {\n return this.getAttribute(\"url\") || \"\";\n }\n\n set url(value: string | null | undefined) {\n reflectAttribute(this, \"url\", value);\n }\n\n get method(): string {\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\n }\n\n set method(value: string | null | undefined) {\n reflectAttribute(this, \"method\", value);\n }\n\n get fieldName(): string {\n return this.getAttribute(\"field-name\") || \"file\";\n }\n\n set fieldName(value: string | null | undefined) {\n reflectAttribute(this, \"field-name\", value);\n }\n\n get multiple(): boolean {\n return this.hasAttribute(\"multiple\");\n }\n\n set multiple(value: boolean | null | undefined) {\n reflectBooleanAttribute(this, \"multiple\", value);\n }\n\n get maxSize(): number {\n const attr = this.getAttribute(\"max-size\");\n if (attr === null) {\n return Infinity;\n }\n // 不正値(NaN になる \"abc\" など)や負数は「制限なし」(Infinity) として扱う。\n // NaN を返すと `size > NaN` が常に false になりサイズ検証が無言で無効化され、\n // 負数を返すと全ファイルが拒否されるため、いずれも安全側の Infinity に丸める。\n const n = parseInt(attr, 10);\n return Number.isFinite(n) && n >= 0 ? n : Infinity;\n }\n\n set maxSize(value: number | null | undefined) {\n reflectAttribute(this, \"max-size\", value);\n }\n\n get accept(): string {\n return this.getAttribute(\"accept\") || \"\";\n }\n\n set accept(value: string | null | undefined) {\n reflectAttribute(this, \"accept\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean | null | undefined) {\n reflectBooleanAttribute(this, \"manual\", value);\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get progress(): number {\n return this._core.progress;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get status(): number {\n return this._core.status;\n }\n\n get errorInfo(): WcsIoErrorInfo | null {\n return this._core.errorInfo;\n }\n\n get promise(): Promise<any> {\n return this._core.promise;\n }\n\n // --- Command properties ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // 進行中に再度 trigger=true が来ても再入ガードはしない(FetchCore シェルと同一)。\n // upload() → _core.upload() が先頭で既存リクエストを abort し新規開始するため、\n // 連続トリガは「前回を中止して新しいアップロードを開始する」挙動になる。\n // 各 upload() の settle ごとに trigger-changed(false) が 1 回発火する。\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.upload().finally(() => {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n });\n }\n }\n\n get files(): FileList | File[] | null {\n return this._files;\n }\n\n set files(value: FileList | File[] | null | undefined) {\n // undefined は「値が無い」= 初期状態(null)。null と同じく files をクリアし、\n // files-changed にも undefined ではなく null を載せる。\n const files = value ?? null;\n this._files = files;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: files,\n bubbles: true,\n }));\n if (!this.manual && files && files.length > 0) {\n if (this.url) this.upload();\n else this._warnNotReady(\"files were assigned while there is no url\");\n }\n }\n\n // --- Validation ---\n\n private _validate(files: FileList | File[]): WcsUploadError | null {\n const maxSize = this.maxSize;\n if (maxSize !== Infinity) {\n for (let i = 0; i < files.length; i++) {\n if (files[i].size > maxSize) {\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\n }\n }\n }\n\n const accept = this.accept;\n if (accept) {\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const fileType = file.type.toLowerCase();\n const fileName = file.name.toLowerCase();\n // file.type が空文字(OS が MIME を判定できないファイル)の場合、MIME 系\n // パターン(`image/*` / 厳密 MIME)は一致しない。その場合でも accept に\n // 拡張子パターン(`.pdf` 等)が含まれ拡張子が一致すれば受理される。\n // accept が MIME 系のみのときは型を確認できないため拒否する(安全側)。\n const matched = acceptList.some(pattern => {\n if (pattern.startsWith(\".\")) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith(\"/*\")) {\n return fileType !== \"\" && fileType.startsWith(pattern.slice(0, -1));\n }\n return fileType !== \"\" && fileType === pattern;\n });\n if (!matched) {\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\n }\n }\n }\n\n return null;\n }\n\n // --- Public methods ---\n\n abort(): void {\n this._core.abort();\n }\n\n async upload(): Promise<any> {\n const files = this._files;\n // url 未設定は no-op(null)。Core は never-throw(url 空なら error プロパティに\n // 載せて null を返す)だが、Shell は url/files のライフサイクルを所有しており\n // 「送信先が無い」を「ファイル無し」と同じ無操作として扱い、Core を呼ぶ前に return する。\n // これにより set trigger / set files の fire-and-forget 経路で unhandled rejection が\n // 発生せず、README の「upload() は全終了ケースで resolve し never reject」契約とも整合する。\n if (!files || files.length === 0 || !this.url) {\n this._warnNotReady(!this.url ? \"there is no url\" : \"there are no files\");\n return null;\n }\n\n const validationError = this._validate(files);\n if (validationError) {\n // Route through the Core so `el.error` (which reads _core.error) reflects\n // the validation failure and stays sticky until the next successful upload,\n // matching the family-wide error contract. The Core dispatches\n // wcs-upload:error on this element (its _target), so the observable event is\n // unchanged.\n this._core.setError(validationError);\n return null;\n }\n\n const result = await this._core.upload(this.url, files, {\n method: this.method,\n fieldName: this.fieldName,\n });\n\n // 自分が開始したアップロードのファイルだけをリセット\n // (途中で新しい files がセットされていたら触らない)\n if (this._files === files) {\n this._files = null;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: null,\n bubbles: true,\n }));\n }\n\n return result;\n }\n\n // A refused upload sent nothing and said nothing (no `error`, by design): a `trigger`\n // written before `url` / `files` in one `data-wcs` (bindings apply in the order\n // written), a retry after the files were used up, files picked before the url is known.\n private _warnNotReady(reason: string): void {\n if (this._told?.has(reason)) return;\n (this._told ??= new Set()).add(reason);\n console.warn(\n `[@wcstack/upload] [wcs/command-not-ready] The upload was refused: ${reason}, so nothing is sent. ` +\n \"Write url and files before trigger (bindings apply in the order written), and assign files again \" +\n \"for each retry: an upload uses them up. (Said once per element and reason.)\",\n this,\n );\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void {\n // 意図的に空。url 変更ではアップロードを自動実行しない(files が必要なため)。\n // observedAttributes のコメント参照。\n }\n\n connectedCallback(): void {\n // upgrade 前に代入された input を取り込み直す(doc 13 §1.2 / Phase A1)\n upgradeProperties(this);\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapUpload(userConfig?: IWritableConfig, registry?: CustomElementRegistry): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents(registry);\n}\n","import { WcsUpload } from \"./components/Upload.js\";\nimport { config } from \"./config.js\";\n\n/**\n * Register this package's tags. Pass a scoped `CustomElementRegistry` to define\n * them for a single shadow tree -- scoped registries do not inherit the global\n * one, so a tree using one needs its own definitions.\n */\nexport function registerComponents(registry: CustomElementRegistry = customElements): void {\n if (!registry.get(config.tagNames.upload)) {\n registry.define(config.tagNames.upload, WcsUpload);\n }\n}\n"],"names":["config","triggerAttribute","tagNames","upload","OperationLane","laneKey","policy","_ownerGeneration","_latestEpoch","_nextOperationId","_activeOperationId","undefined","_activeOperationIds","Set","_queue","_inFlightCount","_terminal","Map","_claimedOutcome","_controllers","_attempts","_withSignal","_trace","constructor","options","this","withSignal","trace","ownerGeneration","inFlightCount","latestEpoch","activeOperationId","begin","supersedeEpoch","_abortController","operationId","ticket","push","add","set","attempt","_makeAttempt","type","retry","has","previous","get","attemptNo","_releaseController","canCommit","status","_isEligible","claimTerminal","outcome","claimedOutcome","finalize","delete","_advanceBookkeeping","signalOf","signal","abort","abortActive","disposeOwner","Array","from","keys","clear","length","AbortController","controller","remaining","filter","t","aborted","assessCapabilities","registry","availability","evaluate","id","spec","probe","requiredAllAvailable","required","a","optionalAllAvailable","optional","readiness","allIds","needsSecure","some","requiresSecureContext","needsActivation","requiresUserActivation","secureContext","globalThis","isSecureContext","userActivation","permission","activity","preconditions","epoch","lastError","requiredCapabilitiesAvailable","assessment","every","WCS_UPLOAD_ERROR_CODE","UPLOAD_CAPABILITIES","XMLHttpRequest","compatKey","UploadCore","EventTarget","static","protocol","version","properties","name","event","semantics","getter","e","detail","value","inputs","commands","async","_target","_value","_loading","_progress","_error","_status","_errorInfo","_xhr","_promise","Promise","resolve","_lane","_ready","target","super","ready","observe","dispose","_setLoading","loading","progress","error","promise","errorInfo","supported","platformAssessment","REQUIRED_CAPABILITIES","_commitStep","step","dispatchEvent","CustomEvent","bubbles","_setProgress","_setError","setError","_setResponse","_setErrorInfo","code","phase","recoverable","message","capabilityId","_commitErrorInfo","info","url","files","p","_doUpload","missing","find","started","method","headers","fieldName","formData","FormData","i","append","xhr","addEventListener","lengthComputable","Math","round","loaded","total","responseText","getResponseHeader","includes","JSON","parse","statusText","body","open","Object","entries","setRequestHeader","send","registered","handleClick","Element","triggerElement","closest","uploadId","getAttribute","UploadCtor","customElements","el","document","getElementById","uploadElement","preventDefault","hasAccessorOnPrototype","proto","getPrototypeOf","descriptor","getOwnPropertyDescriptor","initialAttributes","WeakMap","initialAttribute","byName","writeAttribute","removeAttribute","setAttribute","reflectAttribute","initial","String","reflectBooleanAttribute","WcsUpload","HTMLElement","wcBindable","observedAttributes","_core","_files","_trigger","_told","_connectedCallbackPromise","_internals","_initInternals","_wireStates","d","debugStates","states","attachInternals","internals","map","toStates","debug","hasAttribute","on","toggleAttribute","connectedCallbackPromise","toUpperCase","multiple","maxSize","attr","Infinity","n","parseInt","Number","isFinite","accept","manual","trigger","finally","_warnNotReady","_validate","size","acceptList","split","s","trim","toLowerCase","file","fileType","fileName","pattern","startsWith","endsWith","slice","validationError","result","reason","console","warn","attributeChangedCallback","_name","_oldValue","_newValue","connectedCallback","element","declaration","input","prototype","hasOwnProperty","call","record","upgradeProperties","style","display","disconnectedCallback","define","registerComponents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"auto.min.js","sources":["../src/config.ts","../src/core/operationLane.ts","../src/core/platformCapability.ts","../src/core/uploadCapabilities.ts","../src/core/UploadCore.ts","../src/autoTrigger.ts","../src/protocol/upgradeProperties.ts","../src/protocol/inputAttribute.ts","../src/components/Upload.ts","../src/bootstrapUpload.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n upload: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-uploadtarget\",\n tagNames: {\n upload: \"wcs-upload\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// `config` は内部用のライブビュー(live view)。setConfig() の更新が即座に反映される\n// 実体 `_config` をそのまま公開しており、凍結もクローンもしていない。autoTrigger /\n// components など同パッケージ内のモジュールが最新値を読むための窓口であり、\n// 「変更不可なスナップショット」が必要な外部利用には getConfig()(凍結クローンを返す)\n// を使うこと。型が readonly なのは内部からの誤書き換えを抑止するための表明にすぎない。\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\n/** A misspelt option would otherwise do nothing: `bootstrapUpload` refuses it. */\nfunction invalid(key: string): never {\n throw new Error(`[@wcstack/upload] bootstrapUpload: \"${key}\" is not one of its options, or not of the option's type.`);\n}\n\n/**\n * Applies the options given; an undefined value is left out. An option this package does not\n * have, a value of another type than its default (null, or an array for an object, included) or\n * a tag name it does not define throws, and then nothing is applied.\n */\nexport function setConfig(partialConfig: IWritableConfig): void {\n const options = _config as unknown as Record<string, unknown>;\n const tags = _config.tagNames as Record<string, string>;\n const given = Object.entries(partialConfig).filter(([, value]) => value !== undefined);\n const givenTags = Object.entries(partialConfig.tagNames ?? {}).filter(([, tag]) => tag !== undefined);\n for (const [key, value] of given) {\n const current = options[key];\n if (!Object.hasOwn(options, key) || value === null || typeof value !== typeof current || Array.isArray(value) !== Array.isArray(current)) {\n invalid(key);\n }\n }\n for (const [name, tag] of givenTags) {\n if (!Object.hasOwn(tags, name) || typeof tag !== \"string\") invalid(`tagNames.${name}`);\n }\n for (const [key, value] of given) {\n if (key !== \"tagNames\") {\n options[key] = value;\n }\n }\n for (const [name, tag] of givenTags) tags[name] = tag as string;\n frozenConfig = null;\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /io-core/operation-lane.ts by scripts/sync-io-core.mjs.\n// Run `node scripts/sync-io-core.mjs` after editing the source.\n// ===========================================================================\n\n/**\n * operationLane.ts\n *\n * Phase 4 (docs/architecture-hardening/09-remediation-design.md §5, §5.1) の\n * OperationTicket / CommitGuard / terminal CAS を型付き実装した lane プリミティブ。\n * docs/async-execution-model.md §5 が既に規範化した排他モード\n * (latest / queue / exhaust / overlap) を、`AbortController` だけでは防げない\n * 「取消不能な Promise・abort と同時に完了した結果の commit」から守るための\n * 実行時ガードとして具体化する。\n *\n * 配置方針 (§5): 本ファイルは /io-core/ の単一正典であり、scripts/sync-io-core.mjs が\n * 各 IO ノードの src/core/ へ生成コピー (AUTO-GENERATED, 編集禁止) を配布する。\n * `protocol/wcBindable.ts` と同じ copy-distribution 方式で、ランタイム依存を導入せず\n * 各パッケージのバンドルへ inline される (zero-runtime-dep / 自己完結 CDN を維持)。\n * 編集はこの正典に対して行い、`node scripts/sync-io-core.mjs` で再配布する。\n *\n * 初期 PoC は fetch の `latest` policy から開始した。現在は4 policy 全てを\n * `operationLane.test.ts` が直接検証し、生成コピーを fetch / upload / share /\n * contacts / credential / eyedropper が利用する。lane 自体は promise を実行せず、\n * bookkeeping と guard の状態機械に徹する — 実際の非同期処理は Core が駆動し\n * lane に照合する。\n */\n\n/** §5: 排他モードの語彙。async-execution-model.md §5 の 4 モードに対応 (parallel は予約語・スコープ外)。 */\nexport type LanePolicy = \"latest\" | \"queue\" | \"exhaust\" | \"overlap\";\n\n/** §5: 各 operation の一回限りの終端結果。 */\nexport type TerminalOutcome = \"success\" | \"error\" | \"timeout\" | \"aborted\" | \"stale\";\n\n/** §5: 論理操作 1 件の identity。retry は同じ operationId を再利用する。 */\nexport interface OperationTicket {\n readonly operationId: number;\n /** 発行時に捕捉した I/O Core の observe / reconnect / dispose lifecycle 世代。 */\n readonly ownerGeneration: number;\n readonly laneKey: string;\n readonly policy: LanePolicy;\n /** supersede bookkeeping に使う epoch (latest policy のみ)。 */\n readonly supersedeEpoch?: number;\n}\n\n/** §5: operation の 1 回の試行。retry で attempt++ と resource signal だけ差し替える。 */\nexport interface OperationAttempt {\n readonly operationId: number;\n readonly attempt: number;\n readonly signal?: AbortSignal;\n}\n\n/** §6: DevTools 側 channel へ流す trace(fetch では既定 off・zero-cost)。 */\nexport type OperationTraceEvent =\n | { readonly type: \"io:operation-started\"; readonly operationId: number; readonly laneKey: string; readonly policy: LanePolicy }\n | { readonly type: \"io:operation-retried\"; readonly operationId: number; readonly laneKey: string; readonly attempt: number }\n | { readonly type: \"io:operation-settled\"; readonly operationId: number; readonly laneKey: string; readonly outcome: TerminalOutcome }\n | { readonly type: \"io:stale-dropped\"; readonly operationId: number; readonly laneKey: string };\n\nexport interface OperationLaneOptions {\n /** attempt ごとに AbortController を発行し signal を渡す (fetch/upload 系)。 */\n readonly withSignal?: boolean;\n /**\n * trace subscriber。undefined なら trace record を一切生成しない\n * (§10.3 hook-off zero allocation の gate)。\n */\n readonly trace?: (event: OperationTraceEvent) => void;\n}\n\n/** 内部の終端状態。absence = pending。'committing' は multi-setter commit 中の中間状態。 */\ntype TerminalStatus = \"committing\" | TerminalOutcome;\n\n/**\n * 1 レーン = 独立した排他単位。Core が 1 つ以上所有する (module singleton にしない —\n * 複数 <wcs-fetch> 間で漏れるため)。\n */\nexport class OperationLane {\n readonly laneKey: string;\n readonly policy: LanePolicy;\n\n private _ownerGeneration = 0;\n private _latestEpoch = 0;\n private _nextOperationId = 1;\n // latest / queue / exhaust の単一 active。queue は head を指す。\n private _activeOperationId: number | undefined = undefined;\n // overlap の active set (§5: 内部 bookkeeping のみ・observable 公開はしない)。\n private readonly _activeOperationIds = new Set<number>();\n // queue policy の FIFO。\n private readonly _queue: OperationTicket[] = [];\n private _inFlightCount = 0;\n // opId → 終端状態 (absence = pending)。\n private readonly _terminal = new Map<number, TerminalStatus>();\n // claimTerminal で確定した outcome (finalize が 'committing' を最終値へ移す)。\n private readonly _claimedOutcome = new Map<number, TerminalOutcome>();\n // opId → AbortController (identity は opId が保証。cross-op clobber は構造上起きない)。\n private readonly _controllers = new Map<number, AbortController>();\n // opId → attempt 数。\n private readonly _attempts = new Map<number, number>();\n private readonly _withSignal: boolean;\n private readonly _trace?: (event: OperationTraceEvent) => void;\n\n constructor(laneKey: string, policy: LanePolicy, options: OperationLaneOptions = {}) {\n this.laneKey = laneKey;\n this.policy = policy;\n this._withSignal = options.withSignal ?? false;\n this._trace = options.trace;\n }\n\n get ownerGeneration(): number {\n return this._ownerGeneration;\n }\n\n get inFlightCount(): number {\n return this._inFlightCount;\n }\n\n get latestEpoch(): number {\n return this._latestEpoch;\n }\n\n get activeOperationId(): number | undefined {\n return this._activeOperationId;\n }\n\n /**\n * 新しい要求の到着。arrival policy を適用し ticket + 最初の attempt を発行する。\n * exhaust で実行中の場合だけ null を返す (新要求を ticket 化せず拒否 = 冪等 no-op)。\n */\n begin(): { ticket: OperationTicket; attempt: OperationAttempt } | null {\n let supersedeEpoch: number | undefined;\n switch (this.policy) {\n case \"latest\": {\n // latestEpoch を進め、旧 active を abort (可能なら)。旧 ticket は settle 時に\n // eligibility 不一致で stale となる。\n supersedeEpoch = ++this._latestEpoch;\n if (this._activeOperationId !== undefined) {\n this._abortController(this._activeOperationId);\n }\n break;\n }\n case \"exhaust\": {\n // 実行中なら新要求を拒否 (呼び出し側は既存結果へ合流)。\n if (this._activeOperationId !== undefined) {\n return null;\n }\n break;\n }\n case \"queue\":\n case \"overlap\":\n break;\n }\n\n const operationId = this._nextOperationId++;\n const ticket: OperationTicket = {\n operationId,\n ownerGeneration: this._ownerGeneration,\n laneKey: this.laneKey,\n policy: this.policy,\n supersedeEpoch,\n };\n\n switch (this.policy) {\n case \"latest\":\n case \"exhaust\":\n this._activeOperationId = operationId;\n break;\n case \"queue\":\n this._queue.push(ticket);\n // 先頭だけを active にする (先行が完了するまで待つ)。\n if (this._activeOperationId === undefined) {\n this._activeOperationId = operationId;\n }\n break;\n case \"overlap\":\n this._activeOperationIds.add(operationId);\n break;\n }\n\n this._inFlightCount += 1;\n this._attempts.set(operationId, 1);\n const attempt = this._makeAttempt(operationId, 1);\n if (this._trace !== undefined) {\n this._trace({ type: \"io:operation-started\", operationId, laneKey: this.laneKey, policy: this.policy });\n }\n return { ticket, attempt };\n }\n\n /**\n * retry: 同じ operationId に新しい attempt を作る。attempt number と resource signal\n * だけを更新する (§5)。既に終端した operation には作れない (null)。\n */\n retry(ticket: OperationTicket): OperationAttempt | null {\n if (ticket.ownerGeneration !== this._ownerGeneration) return null;\n if (this._terminal.has(ticket.operationId)) return null;\n const previous = this._attempts.get(ticket.operationId);\n if (previous === undefined) return null;\n const attemptNo = previous + 1;\n this._attempts.set(ticket.operationId, attemptNo);\n // 前の attempt の signal は破棄し、新しい controller を張る。\n this._releaseController(ticket.operationId);\n const attempt = this._makeAttempt(ticket.operationId, attemptNo);\n if (this._trace !== undefined) {\n this._trace({ type: \"io:operation-retried\", operationId: ticket.operationId, laneKey: this.laneKey, attempt: attemptNo });\n }\n return attempt;\n }\n\n /**\n * CommitGuard (§5.1)。外部可視の setter / event dispatch の直前に呼ぶ。\n * (1) owner lifecycle generation 一致 (2) terminal settle 前 (3) policy eligibility。\n */\n canCommit(ticket: OperationTicket): boolean {\n if (ticket.ownerGeneration !== this._ownerGeneration) return false;\n const status = this._terminal.get(ticket.operationId);\n // absence = pending / 'committing' = multi-setter commit 中。どちらも settle 前。\n if (status !== undefined && status !== \"committing\") return false;\n return this._isEligible(ticket);\n }\n\n /**\n * terminal CAS (§5.1): pending → committing を claim する。勝者だけが true。\n * eligibility / owner gen を満たさない場合も false。claim 後は commit 中となり、\n * canCommit は各 setter の直前で再検査する (setter が同期 supersede しても取りこぼさない)。\n */\n claimTerminal(ticket: OperationTicket, outcome: TerminalOutcome): boolean {\n if (ticket.ownerGeneration !== this._ownerGeneration) return false;\n if (this._terminal.has(ticket.operationId)) return false; // 既に committing / 終端\n if (!this._isEligible(ticket)) return false;\n this._terminal.set(ticket.operationId, \"committing\");\n this._claimedOutcome.set(ticket.operationId, outcome);\n return true;\n }\n\n /** claim 済み outcome (timer が claim → catch が読む等)。未 claim なら undefined。 */\n claimedOutcome(ticket: OperationTicket): TerminalOutcome | undefined {\n return this._claimedOutcome.get(ticket.operationId);\n }\n\n /**\n * operation の後始末。claim 済みなら outcome を確定し、未 claim なら stale-drop。\n * controller を解放し in-flight を減らし、policy の bookkeeping を進める。冪等。\n */\n finalize(ticket: OperationTicket): void {\n const operationId = ticket.operationId;\n const status = this._terminal.get(operationId);\n if (status !== undefined && status !== \"committing\") {\n // 既に確定済み。冪等に return。\n return;\n }\n let outcome: TerminalOutcome;\n if (status === \"committing\") {\n outcome = this._claimedOutcome.get(operationId) ?? \"stale\";\n } else {\n // 一度も claim されなかった (supersede / dispose で eligibility を失った)。\n outcome = \"stale\";\n }\n this._terminal.set(operationId, outcome);\n this._claimedOutcome.delete(operationId);\n this._releaseController(operationId);\n this._attempts.delete(operationId);\n if (this._inFlightCount > 0) this._inFlightCount -= 1;\n this._advanceBookkeeping(operationId);\n if (this._trace !== undefined) {\n if (outcome === \"stale\") {\n this._trace({ type: \"io:stale-dropped\", operationId, laneKey: this.laneKey });\n } else {\n this._trace({ type: \"io:operation-settled\", operationId, laneKey: this.laneKey, outcome });\n }\n }\n }\n\n /** operation の signal (resource 解放用)。withSignal でなければ undefined。 */\n signalOf(ticket: OperationTicket): AbortSignal | undefined {\n return this._controllers.get(ticket.operationId)?.signal;\n }\n\n /** best-effort な resource 中断。正しさは owner gen / eligibility / terminal CAS が担う。 */\n abort(ticket: OperationTicket): void {\n this._abortController(ticket.operationId);\n }\n\n /**\n * 現在 active な operation を中断する (利用者による明示キャンセル)。epoch は進めない —\n * 中断された operation は eligibility を保ったまま 'aborted' を claim できる\n * (loading をクリアしつつ in-flight 状態を残す)。\n */\n abortActive(): void {\n if (this._activeOperationId !== undefined) {\n this._abortController(this._activeOperationId);\n }\n for (const operationId of this._activeOperationIds) {\n this._abortController(operationId);\n }\n }\n\n /**\n * dispose (§4.1 world generation)。owner generation を bump して全 ticket を無効化し、\n * 生きている controller を全て abort する。dispose 後に settle した operation は\n * owner gen 不一致で外部 commit しない。retention gate (§10.3) のため live な\n * 全 operation を即時に stale として finalize し、controller / attempt を解放する。\n */\n disposeOwner(): void {\n this._ownerGeneration += 1;\n for (const operationId of Array.from(this._controllers.keys())) {\n this._abortController(operationId);\n // finalize は dispose 後 (terminal='stale') に early-return するため controller を\n // 解放しない。retention gate (§10.3) を満たすためここで明示的に解放する。\n this._releaseController(operationId);\n }\n for (const operationId of Array.from(this._attempts.keys())) {\n if (!this._terminal.has(operationId)) {\n this._terminal.set(operationId, \"stale\");\n }\n this._claimedOutcome.delete(operationId);\n this._attempts.delete(operationId);\n if (this._trace !== undefined) {\n this._trace({ type: \"io:stale-dropped\", operationId, laneKey: this.laneKey });\n }\n }\n this._activeOperationId = undefined;\n this._activeOperationIds.clear();\n this._queue.length = 0;\n this._inFlightCount = 0;\n }\n\n // --- internal ---\n\n private _makeAttempt(operationId: number, attemptNo: number): OperationAttempt {\n let signal: AbortSignal | undefined;\n // AbortController 不在環境(古い runtime / 一部 SSR)では degraded: signal なしで進む。\n // 正しさは owner generation / eligibility / terminal CAS が担うため、native 中断が\n // 無くても supersede / dispose は機能する(best-effort resource 中断が省かれるだけ)。\n if (this._withSignal && typeof AbortController === \"function\") {\n const controller = new AbortController();\n this._controllers.set(operationId, controller);\n signal = controller.signal;\n }\n return { operationId, attempt: attemptNo, signal };\n }\n\n private _isEligible(ticket: OperationTicket): boolean {\n switch (this.policy) {\n case \"latest\":\n return ticket.supersedeEpoch === this._latestEpoch;\n case \"queue\":\n case \"exhaust\":\n return this._activeOperationId === ticket.operationId;\n case \"overlap\":\n return this._activeOperationIds.has(ticket.operationId);\n }\n }\n\n private _advanceBookkeeping(operationId: number): void {\n switch (this.policy) {\n case \"latest\":\n case \"exhaust\":\n if (this._activeOperationId === operationId) {\n this._activeOperationId = undefined;\n }\n break;\n case \"queue\": {\n // 完了した ticket を FIFO から取り除き、次の先頭を active にする。filter で\n // 「先頭 / 非先頭 / 不在」を一様に扱う (finalize は冪等ガードを通った op のみ到達)。\n const remaining = this._queue.filter((t) => t.operationId !== operationId);\n this._queue.length = 0;\n this._queue.push(...remaining);\n this._activeOperationId = this._queue.length > 0 ? this._queue[0].operationId : undefined;\n break;\n }\n case \"overlap\":\n this._activeOperationIds.delete(operationId);\n break;\n }\n }\n\n private _abortController(operationId: number): void {\n const controller = this._controllers.get(operationId);\n if (controller !== undefined && !controller.signal.aborted) {\n controller.abort();\n }\n }\n\n private _releaseController(operationId: number): void {\n this._controllers.delete(operationId);\n }\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /io-core/platform-capability.ts by scripts/sync-io-core.mjs.\n// Run `node scripts/sync-io-core.mjs` after editing the source.\n// ===========================================================================\n\n/**\n * platform-capability.ts\n *\n * Phase 6(docs/architecture-hardening/09-remediation-design.md §7.2 /\n * 07-browser-capability-variance.md)の browser capability 判定と error taxonomy の\n * 汎用プリミティブ。node 固有の capability registry / error code は各パッケージが\n * 別ファイルで宣言し、この汎用層(型 + assess 機構)を import する。\n *\n * 原則:\n * - feature detection は境界(利用直前)で行う。module 評価時に browser global を\n * 参照しない(SSR / worker で import が失敗しない)。\n * - capability ID(`web.fetch` 等)は文字列を global property path として eval せず、\n * registry が ID ごとに副作用のない presence probe を対応付ける。\n * - availability / permission / readiness / activity / operation error を 1 つの\n * `ready / unsupported / error` enum に畳まない。required 欠如は開始しない、\n * optional 欠如は宣言済み fallback で readiness を `degraded` にする。\n *\n * 配置: 本ファイルは /io-core/ の単一正典であり、scripts/sync-io-core.mjs が\n * 各 IO ノードの src/core/ へ生成コピー (AUTO-GENERATED, 編集禁止) を配布する。\n * `protocol/wcBindable.ts` と同じ copy-distribution 方式で、ランタイム依存を導入せず\n * 各パッケージのバンドルへ inline される (zero-runtime-dep / 自己完結 CDN を維持)。\n * 編集はこの正典に対して行い、`node scripts/sync-io-core.mjs` で再配布する。\n *\n * pure(module 評価時に browser global 非参照)。\n */\n\nexport type Availability = \"available\" | \"missing\" | \"unknown\";\nexport type PermissionState = \"granted\" | \"denied\" | \"prompt\" | \"not-applicable\" | \"unknown\";\nexport type Readiness = \"idle\" | \"ready\" | \"degraded\";\nexport type Activity = \"inactive\" | \"active\";\nexport type PreconditionState = \"satisfied\" | \"required\" | \"not-applicable\";\n\n/** operation error の phase(taxonomy)。 */\nexport type WcsIoErrorPhase = \"probe\" | \"start\" | \"execute\" | \"decode\" | \"commit\" | \"dispose\";\n\n/** serializable な error info(non-cloneable な cause とは分離。DevTools / remote へは info のみ)。 */\nexport interface WcsIoErrorInfo {\n readonly code: string;\n readonly phase: WcsIoErrorPhase;\n readonly recoverable: boolean;\n readonly capabilityId?: string;\n readonly message: string;\n}\n\nexport interface PlatformAssessment {\n readonly availability: ReadonlyMap<string, Availability>;\n readonly permission: PermissionState;\n readonly readiness: Readiness;\n readonly activity: Activity;\n readonly preconditions: {\n readonly secureContext: PreconditionState;\n readonly userActivation: PreconditionState;\n };\n readonly epoch: number;\n readonly lastError?: WcsIoErrorInfo;\n}\n\n/** capability 1 件の仕様。probe は副作用なく presence を返す(利用直前に呼ぶ)。 */\nexport interface CapabilitySpec {\n readonly probe: () => boolean;\n readonly requiresSecureContext?: boolean;\n readonly requiresUserActivation?: boolean;\n /** browser compatibility dataset のキー(任意・診断用)。 */\n readonly compatKey?: string;\n}\n\nexport type CapabilityRegistry = ReadonlyMap<string, CapabilitySpec>;\n\nexport interface AssessOptions {\n readonly required: readonly string[];\n readonly optional?: readonly string[];\n readonly permission?: PermissionState;\n readonly activity?: Activity;\n readonly epoch?: number;\n readonly lastError?: WcsIoErrorInfo;\n}\n\nfunction isSecureContext(): boolean {\n return (globalThis as { isSecureContext?: unknown }).isSecureContext === true;\n}\n\n/**\n * capability を利用直前に評価して PlatformAssessment を作る。\n * required が 1 つでも欠ければ readiness は \"idle\"(開始不可)、\n * required 揃い + optional 欠けは \"degraded\"、全揃いは \"ready\"。\n */\nexport function assessCapabilities(registry: CapabilityRegistry, options: AssessOptions): PlatformAssessment {\n const availability = new Map<string, Availability>();\n const evaluate = (id: string): Availability => {\n const spec = registry.get(id);\n if (spec === undefined) return \"unknown\";\n return spec.probe() ? \"available\" : \"missing\";\n };\n\n let requiredAllAvailable = true;\n for (const id of options.required) {\n const a = evaluate(id);\n availability.set(id, a);\n if (a !== \"available\") requiredAllAvailable = false;\n }\n let optionalAllAvailable = true;\n for (const id of options.optional ?? []) {\n const a = evaluate(id);\n availability.set(id, a);\n if (a !== \"available\") optionalAllAvailable = false;\n }\n\n const readiness: Readiness = !requiredAllAvailable ? \"idle\" : (optionalAllAvailable ? \"ready\" : \"degraded\");\n\n // preconditions: 対象 capability のいずれかが要求する場合だけ評価する。\n const allIds = [...options.required, ...(options.optional ?? [])];\n const needsSecure = allIds.some((id) => registry.get(id)?.requiresSecureContext === true);\n const needsActivation = allIds.some((id) => registry.get(id)?.requiresUserActivation === true);\n const secureContext: PreconditionState = needsSecure ? (isSecureContext() ? \"satisfied\" : \"required\") : \"not-applicable\";\n const userActivation: PreconditionState = needsActivation ? \"required\" : \"not-applicable\";\n\n return {\n availability,\n permission: options.permission ?? \"not-applicable\",\n readiness,\n activity: options.activity ?? \"inactive\",\n preconditions: { secureContext, userActivation },\n epoch: options.epoch ?? 0,\n lastError: options.lastError,\n };\n}\n\n/** availability から「required がすべて available か」を判定するヘルパ(supported の最低条件)。 */\nexport function requiredCapabilitiesAvailable(assessment: PlatformAssessment, required: readonly string[]): boolean {\n return required.every((id) => assessment.availability.get(id) === \"available\");\n}\n\n/**\n * このページで機能が使えない理由(使える、または分からないなら null)。利用直前に読む。\n *\n * - `\"insecure-context\"`: 安全なコンテキストではない(`isSecureContext === false`)。\n * Permissions API が扱う機能はどれも安全なコンテキストを要る。\n * - `\"policy-blocked\"`: Permissions-Policy(サーバーのヘッダ、または `allow` の無い\n * `<iframe>`)がその機能を切っている。\n *\n * どちらも Permissions API は教えない: Chromium はポリシーで切られた文書でも\n * `granted` を、安全でない origin では `denied` を返す。利用者の拒否と区別するため、\n * 見張り役(`<wcs-permission>`)も取りに行く側も `unsupported` を報告する\n * (docs/v4-direction-2026-10.md の決定、state-field-report)。\n * `isSecureContext` が無い環境(SSR・テスト)は判断しない。\n */\nexport type FeatureUnavailableReason = \"insecure-context\" | \"policy-blocked\";\n\n/** Permissions-Policy が制御する機能(permission 名と同じ文字列)。 */\nconst POLICY_CONTROLLED = new Set([\n \"camera\", \"microphone\", \"geolocation\", \"midi\", \"clipboard-read\", \"clipboard-write\",\n \"screen-wake-lock\", \"idle-detection\", \"accelerometer\", \"gyroscope\", \"magnetometer\",\n \"ambient-light-sensor\", \"display-capture\",\n]);\n\ninterface PolicyLike { allowsFeature(feature: string): boolean }\n\nexport function featureUnavailable(feature: string): FeatureUnavailableReason | null {\n const g = globalThis as { isSecureContext?: unknown; document?: { permissionsPolicy?: PolicyLike; featurePolicy?: PolicyLike } };\n if (g.isSecureContext === false) return \"insecure-context\";\n if (!POLICY_CONTROLLED.has(feature)) return null;\n const policy = g.document?.permissionsPolicy ?? g.document?.featurePolicy;\n if (policy === undefined || typeof policy.allowsFeature !== \"function\") return null;\n try {\n return policy.allowsFeature(feature) ? null : \"policy-blocked\";\n } catch {\n return null;\n }\n}\n\n/** `featureUnavailable` の理由を、作者が直し方を読める文にする。`what` は文頭(「The camera」など)。 */\nexport function featureUnavailableMessage(what: string, feature: string, reason: FeatureUnavailableReason): string {\n return reason === \"insecure-context\"\n ? `${what} needs a secure context (https:, or http://localhost), and this page is not one.`\n : `${what} is turned off for this page by a Permissions-Policy: the server's Permissions-Policy header, ` +\n `or an <iframe> without allow=\"${feature}\". The browser's site settings cannot change that.`;\n}\n","/**\n * uploadCapabilities.ts\n *\n * Upload node 固有の capability registry と error code。汎用の assess 機構・型は\n * `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から\n * import する。node 固有の宣言はこのハンドライトファイルに置き、生成コピーとは分離する。\n */\n\nimport { CapabilityRegistry, CapabilitySpec } from \"./platformCapability.js\";\n\n/** 安定した upload error code(taxonomy)。値は公開キーとして固定。 */\nexport const WCS_UPLOAD_ERROR_CODE = {\n CapabilityMissing: \"capability-missing\",\n InvalidArgument: \"invalid-argument\",\n Network: \"network\",\n HttpError: \"http-error\",\n} as const;\n\n/**\n * upload node の capability registry。`XMLHttpRequest`(progress 取得のため fetch では\n * なく XHR を用いる)の presence を probe する。\n */\nexport const UPLOAD_CAPABILITIES: CapabilityRegistry = new Map<string, CapabilitySpec>([\n [\"web.xhr\", { probe: () => typeof (globalThis as { XMLHttpRequest?: unknown }).XMLHttpRequest === \"function\", compatKey: \"api.XMLHttpRequest\" }],\n]);\n","import { IWcBindable } from \"../types.js\";\nimport { OperationLane, OperationTicket } from \"./operationLane.js\";\nimport {\n PlatformAssessment,\n WcsIoErrorInfo,\n WcsIoErrorPhase,\n assessCapabilities,\n requiredCapabilitiesAvailable,\n} from \"./platformCapability.js\";\nimport { UPLOAD_CAPABILITIES, WCS_UPLOAD_ERROR_CODE } from \"./uploadCapabilities.js\";\n\nexport interface UploadRequestOptions {\n method?: string;\n headers?: Record<string, string>;\n fieldName?: string;\n}\n\nexport class UploadCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-upload:response\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-upload:loading-changed\", semantics: \"state\" },\n { name: \"progress\", event: \"wcs-upload:progress\", semantics: \"state\" },\n { name: \"error\", event: \"wcs-upload:error\", semantics: \"state\" },\n { name: \"status\", event: \"wcs-upload:response\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.status },\n // Serializable failure taxonomy (stable code / phase / recoverable), or null.\n // Additive bindable output; the existing `error` property/event are unchanged.\n // Fires its own `wcs-upload:error-info-changed` event; no getter, so the bound\n // value is the event detail (mirrors `error` / `loading`). An abort() is not a\n // failure — it clears loading without setting error/errorInfo.\n { name: \"errorInfo\", event: \"wcs-upload:error-info-changed\", semantics: \"state\" },\n ],\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n ],\n commands: [\n { name: \"upload\", async: true },\n { name: \"abort\" },\n ],\n };\n\n // Required capability (probed at call time, never at module eval).\n private static readonly REQUIRED_CAPABILITIES = [\"web.xhr\"] as const;\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _progress: number = 0;\n private _error: any = null;\n private _status: number = 0;\n private _errorInfo: WcsIoErrorInfo | null = null;\n private _xhr: XMLHttpRequest | null = null;\n private _promise: Promise<any> = Promise.resolve(null);\n // Concurrency lane (io-core). `latest`: a new upload supersedes the in-flight one\n // (switchMap). `withSignal: false`: upload uses XMLHttpRequest.abort() rather than\n // an AbortSignal, so the lane owns epoch / commit-guard while abort() below owns\n // the XHR cancellation. dispose() bumps the owner generation and aborts the XHR.\n private _lane = new OperationLane(\"upload\", \"latest\", { withSignal: false });\n // SSR: no asynchronous probe to await, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). Upload is command-driven with no subscription to establish,\n // so observe() is an idempotent no-op that resolves once ready; dispose() bumps\n // the lane's owner generation (invalidating any in-flight upload) and aborts the\n // XHR.\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this._lane.disposeOwner();\n this.abort();\n // The aborted upload's handler can no longer claim its end (the owner generation\n // moved), so it is published here (timing-and-firing-contract §22): a route the\n // element leaves keeps its nodes — bindings included — for the next entry, and\n // state would keep `loading`. `progress` stays where the transfer stopped, as on\n // any abort. (`loading-changed` is not same-value guarded: only a change is sent.)\n if (this._loading) this._setLoading(false);\n }\n\n get value(): any {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get progress(): number {\n return this._progress;\n }\n\n get error(): any {\n return this._error;\n }\n\n get status(): number {\n return this._status;\n }\n\n get promise(): Promise<any> {\n return this._promise;\n }\n\n /**\n * The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /\n * `recoverable` / `capabilityId`), or null. Exposed as an additive wc-bindable\n * property (event `wcs-upload:error-info-changed`); the existing `error`\n * property/event are unchanged. An abort() is not a failure (no errorInfo).\n */\n get errorInfo(): WcsIoErrorInfo | null {\n return this._errorInfo;\n }\n\n /**\n * Whether the required platform capability (`web.xhr`) is available right now —\n * decided by call-time feature detection, not User-Agent. Core-only, additive.\n */\n get supported(): boolean {\n return requiredCapabilitiesAvailable(this.platformAssessment, UploadCore.REQUIRED_CAPABILITIES);\n }\n\n /**\n * Full platform assessment (availability / readiness / preconditions), probed at\n * call time. Core-only opt-in dev / sidecar view.\n */\n get platformAssessment(): PlatformAssessment {\n return assessCapabilities(UPLOAD_CAPABILITIES, {\n required: UploadCore.REQUIRED_CAPABILITIES,\n activity: this._loading ? \"active\" : \"inactive\",\n lastError: this._errorInfo ?? undefined,\n });\n }\n\n // CommitGuard (§5.1): external setters / event dispatch only run if the ticket\n // still holds owner generation, is pre-terminal, and is the lane's latest epoch\n // (a superseding upload can invalidate a ticket mid-commit).\n private _commitStep(ticket: OperationTicket, step: () => void): void {\n if (this._lane.canCommit(ticket)) {\n step();\n }\n }\n\n // --- State setters with event dispatch ---\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setProgress(progress: number): void {\n this._progress = progress;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\n detail: progress,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n // Same-value guard (async-io-node-guidelines.md §3.3). `error` is state-ish,\n // so suppressing redundant null→null dispatches (every upload start clears a\n // usually-already-null error) avoids a spurious wcs-upload:error per\n // successful upload. Reference identity is sufficient: each failure builds a\n // fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Surface a Shell-originated error (e.g. maxSize / accept validation, which the\n // Core has no knowledge of) on the shared `error` property so `el.error` stays\n // sticky and consistent with Core-originated errors — same error contract as the\n // rest of the @wcstack IO nodes. A later successful upload() clears it via\n // _setError(null). Dispatches wcs-upload:error like any other error transition.\n setError(error: any): void {\n this._setError(error);\n }\n\n private _setResponse(value: any, status: number): void {\n this._value = value;\n this._status = status;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\n detail: { value, status },\n bubbles: true,\n }));\n }\n\n // Single mutation point for `errorInfo`, mirroring `_setError`'s same-value guard\n // and event dispatch so the additive `errorInfo` wc-bindable property stays in\n // sync with `error`. Each failure builds a fresh object (reference guard passes);\n // the clear path passes null (suppresses a redundant null→null per upload start).\n private _setErrorInfo(code: string, phase: WcsIoErrorPhase, recoverable: boolean, message: string, capabilityId?: string): void {\n this._commitErrorInfo({ code, phase, recoverable, message, ...(capabilityId === undefined ? {} : { capabilityId }) });\n }\n\n private _commitErrorInfo(info: WcsIoErrorInfo | null): void {\n if (this._errorInfo === info) return;\n this._errorInfo = info;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error-info-changed\", {\n detail: info,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n abort(): void {\n // Abort the current XHR. Its `abort` event handler claims the `aborted` terminal\n // (while the ticket is still latest — abort() runs before a superseding upload's\n // begin()), unifying the loading-release path with success/error/network. When a\n // superseding upload or dispose() has already advanced the epoch/owner gen, the\n // handler's claim fails and it writes nothing (stale-drop).\n if (this._xhr) {\n this._xhr.abort();\n this._xhr = null;\n }\n }\n\n async upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\n // never-throw: 引数バリデーション失敗は例外ではなく error プロパティに流し、\n // サニタイズ値(null)を返す。command-token 経路からの呼び出しが unhandled\n // rejection にならず、「upload() は全終了ケースで resolve」契約とも整合する。\n if (!url) {\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.InvalidArgument, \"start\", false, \"url is required.\");\n this._setError({ message: \"url is required.\" });\n return null;\n }\n if (!files || files.length === 0) {\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.InvalidArgument, \"start\", false, \"files are required.\");\n this._setError({ message: \"files are required.\" });\n return null;\n }\n\n const p = this._doUpload(url, files, options);\n this._promise = p;\n return p;\n }\n\n // --- Internal ---\n\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\n // Probe the required capability just before starting (SSR / very old runtime).\n const assessment = this.platformAssessment;\n if (!requiredCapabilitiesAvailable(assessment, UploadCore.REQUIRED_CAPABILITIES)) {\n const missing = UploadCore.REQUIRED_CAPABILITIES.find((id) => assessment.availability.get(id) !== \"available\");\n const message = `Required capability \"${missing}\" is unavailable.`;\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.CapabilityMissing, \"start\", false, message, missing);\n this._setError({ message });\n return Promise.resolve(null);\n }\n\n // Abort the previous XHR BEFORE advancing the epoch, so its `abort` handler\n // claims `aborted` while still latest (preserving the loading true→false→true\n // supersede sequence). Then begin() advances the epoch for THIS upload.\n this.abort();\n const started = this._lane.begin()!; // `latest` begin never returns null\n const { ticket } = started;\n\n this._commitStep(ticket, () => this._setLoading(true));\n this._commitStep(ticket, () => {\n this._setProgress(0);\n this._commitErrorInfo(null);\n this._setError(null);\n });\n\n const {\n method = \"POST\",\n headers = {},\n fieldName = \"file\",\n } = options;\n\n const formData = new FormData();\n for (let i = 0; i < files.length; i++) {\n formData.append(fieldName, files[i]);\n }\n\n return new Promise<any>((resolve) => {\n const xhr = new XMLHttpRequest();\n this._xhr = xhr;\n\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\n // Guarded: a superseded / disposed upload's late progress writes nothing.\n this._commitStep(ticket, () => {\n if (event.lengthComputable) {\n this._setProgress(Math.round((event.loaded / event.total) * 100));\n }\n });\n });\n\n xhr.addEventListener(\"load\", () => {\n this._xhr = null;\n if (xhr.status >= 200 && xhr.status < 300) {\n if (!this._lane.claimTerminal(ticket, \"success\")) { resolve(null); this._lane.finalize(ticket); return; }\n let value: any = xhr.responseText;\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n try { value = JSON.parse(xhr.responseText); } catch { /* テキストのまま */ }\n }\n this._commitStep(ticket, () => this._setProgress(100));\n this._commitStep(ticket, () => this._setResponse(value, xhr.status));\n this._commitStep(ticket, () => this._setLoading(false));\n this._lane.finalize(ticket);\n resolve(value);\n } else {\n if (!this._lane.claimTerminal(ticket, \"error\")) { resolve(null); this._lane.finalize(ticket); return; }\n const error = { status: xhr.status, statusText: xhr.statusText, body: xhr.responseText };\n this._commitStep(ticket, () => {\n this._status = xhr.status; // HTTP error keeps status (no wcs-upload:response — value not reset)\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.HttpError, \"execute\", true, `HTTP ${xhr.status} ${xhr.statusText}`);\n this._setError(error);\n });\n this._commitStep(ticket, () => this._setLoading(false));\n this._lane.finalize(ticket);\n resolve(null);\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n this._xhr = null;\n if (!this._lane.claimTerminal(ticket, \"error\")) { resolve(null); this._lane.finalize(ticket); return; }\n const message = \"Network error\";\n this._commitStep(ticket, () => {\n this._setErrorInfo(WCS_UPLOAD_ERROR_CODE.Network, \"execute\", true, message);\n this._setError({ message });\n });\n this._commitStep(ticket, () => this._setLoading(false));\n this._lane.finalize(ticket);\n resolve(null);\n });\n\n xhr.addEventListener(\"abort\", () => {\n this._xhr = null;\n // abort is a routine cancellation, not a failure: claim the `aborted`\n // terminal and clear loading only (no error/errorInfo). A superseded /\n // disposed ticket fails the claim and drops.\n if (this._lane.claimTerminal(ticket, \"aborted\")) {\n this._commitStep(ticket, () => this._setLoading(false));\n }\n this._lane.finalize(ticket);\n resolve(null);\n });\n\n xhr.open(method, url);\n\n for (const [name, value] of Object.entries(headers)) {\n xhr.setRequestHeader(name, value);\n }\n\n xhr.send(formData);\n });\n }\n}\n","import { config } from \"./config.js\";\nimport type { WcsUpload } from \"./components/Upload.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\n if (!uploadId) return;\n\n // Resolve the registered constructor at call time instead of importing WcsUpload\n // as a value. The value import created a components/Upload.ts ⇄ autoTrigger.ts\n // cycle (WcsUpload.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-upload> class matches — without the import cycle.\n const UploadCtor = customElements.get(config.tagNames.upload);\n const el = document.getElementById(uploadId);\n if (!UploadCtor || !(el instanceof UploadCtor)) return;\n const uploadElement = el as WcsUpload;\n\n // ファイルと URL が揃っている場合のみ既定動作を抑止\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\n event.preventDefault();\n }\n uploadElement.upload();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/upgrade-properties.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// custom element の property upgrade — `static wcBindable.inputs` に宣言した入力のうち、\n// 要素が upgrade される前に代入された own データプロパティを取り込み直す。\n//\n// なぜ必要か:\n// 未定義タグの要素は素の HTMLElement なので、`el.url = \"...\"` は own データプロパティを作る。\n// upgrade 後にクラスの accessor が prototype へ入っても own プロパティが優先されるため、\n// setter は二度と呼ばれず、値は要素へ届かないまま消える(エラーも警告も出ない)。\n// 常にプロパティ代入を行う framework(Angular の `[prop]`、Lit の `.prop=`、\n// Solid の `prop:`、Vue の `.prop` 修飾子)× 遅延定義(autoloader / CDN / code-split)で\n// 常態的に起きる。docs/architecture-hardening/13-framework-adapter-binding-constraints.md §1.2。\n//\n// 安全側の判定:\n// own プロパティがあっても、prototype チェーンに accessor が無ければ「シャドウ」ではなく\n// その own プロパティ自体が正規の格納先なので触らない(public class field を壊さない)。\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/upgrade-properties.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/upgradeProperties.ts). Those copies are generated — do not edit them.\nimport { IWcBindable } from \"./wcBindable.js\";\n\nfunction hasAccessorOnPrototype(target: object, name: string): boolean {\n let proto = Object.getPrototypeOf(target);\n while (proto !== null) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, name);\n if (descriptor !== undefined) {\n return typeof descriptor.get === \"function\" || typeof descriptor.set === \"function\";\n }\n proto = Object.getPrototypeOf(proto);\n }\n return false;\n}\n\n// 属性になってしまったオブジェクトの入力(`files=\"[object File]\"`)を、要素ごとに 1 回だけ言う。\n// React 19 は定義前の要素にプロパティが無いのでオブジェクトを属性に書き、Vue の `.attr` も\n// 書く。要素はその入力をプロパティでしか読まないので、何も受け取らず、何も言わなかった\n// (docs/seam-apps.md、fw-inventory)。\nconst toldObjectAttribute = new WeakSet<object>();\n\nfunction warnObjectAttribute(element: object, name: string, value: string): void {\n if (toldObjectAttribute.has(element)) return;\n toldObjectAttribute.add(element);\n const tag = (element as { localName?: string }).localName ?? \"element\";\n console.warn(\n `[wcs/input-as-attribute] <${tag}> has the attribute ${name}=\"${value}\": an object was written as an ` +\n `attribute, so the element did not receive it. A framework does that when the property is set before the ` +\n `element's definition loads (React 19), or when told to (Vue's .attr). Load the definition before rendering, ` +\n `or assign the property through a ref (Vue: .prop). (Said once per element.)`,\n element,\n );\n}\n\n/**\n * `connectedCallback` の先頭で呼ぶ。宣言済み input のうち upgrade 前の代入で\n * accessor をシャドウしている own プロパティを、delete → 再代入で setter に通し直す。\n *\n * - 冪等: 再代入は accessor を通るので own プロパティは残らず、2 回目以降は no-op。\n * - 宣言に `inputs` が無い要素、`wcBindable` を持たない要素では何もしない。\n * - 値の意味は変えない。今まで捨てられていた代入が届くようになる一方向の変化。\n * - 値が `[object …]` の属性(属性に書かれてしまったオブジェクトの入力)は、要素ごとに 1 回警告する。\n */\nexport function upgradeProperties(element: object): void {\n const declaration = (element as { constructor?: { wcBindable?: IWcBindable } }).constructor?.wcBindable;\n const inputs = declaration?.inputs;\n if (inputs === undefined) return;\n const getAttribute = (element as { getAttribute?: (name: string) => string | null }).getAttribute;\n for (const input of inputs) {\n const name = input.name;\n const attribute = typeof getAttribute === \"function\" ? getAttribute.call(element, name.toLowerCase()) : null;\n if (attribute !== null && attribute.startsWith(\"[object \")) warnObjectAttribute(element, name, attribute);\n if (!Object.prototype.hasOwnProperty.call(element, name)) continue;\n if (!hasAccessorOnPrototype(element, name)) continue;\n const record = element as Record<string, unknown>;\n const value = record[name];\n delete record[name];\n record[name] = value;\n }\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/input-attribute.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// 属性へ反映する wc-bindable 入力の producer 側(SPEC-extensions § Producer guidance for inputs の P1〜P3)。\n// 入力の setter は属性をこの 2 関数で書く。それで次が揃う:\n// - `undefined` は「値が無い」(P1): 属性を、この関数で最初に書く前の状態 — マークアップに書かれた値、\n// 無ければ属性なし(= その入力の文書化した既定値)— へ戻す。applier プロファイルを宣言する binder は\n// 値の後の `undefined` を書き(A2)、React 19 も書き、直接の代入でも届く。\n// - `null` はクリア(P2): 属性なし、つまり文書化した既定値。\n// - どちらも文字列 \"undefined\" / \"null\" として属性に入らない。\n//\n// 「最初に書く前」は、その最初の書き込みのときに読む(遅延)。upgrade 前に代入されたプロパティは\n// connectedCallback の upgradeProperties() が通し直すので、そのときにはパーサが書いた属性が揃っている。\n// 要素自身が setter を通さずに書いた属性は、最初の書き込みより前なら「最初の状態」に含まれる。\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/input-attribute.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/inputAttribute.ts). Those copies are generated — do not edit them.\n\nconst initialAttributes = new WeakMap<Element, Map<string, string | null>>();\n\n/** The attribute as it stood before the first write through these helpers. */\nfunction initialAttribute(el: Element, name: string): string | null {\n let byName = initialAttributes.get(el);\n if (byName === undefined) {\n byName = new Map();\n initialAttributes.set(el, byName);\n }\n if (!byName.has(name)) byName.set(name, el.getAttribute(name));\n return byName.get(name) as string | null;\n}\n\nfunction writeAttribute(el: Element, name: string, value: string | null): void {\n if (value === null) el.removeAttribute(name);\n else el.setAttribute(name, value);\n}\n\n/**\n * A value attribute. `value` is written as `String(value)`; `null` removes the attribute;\n * `undefined` restores the attribute the element started with.\n */\nexport function reflectAttribute(el: Element, name: string, value: unknown): void {\n const initial = initialAttribute(el, name);\n writeAttribute(el, name, value === undefined ? initial : value === null ? null : String(value));\n}\n\n/**\n * A boolean attribute, present while `value` is truthy (`null` and `false` remove it);\n * `undefined` restores the attribute the element started with.\n */\nexport function reflectBooleanAttribute(el: Element, name: string, value: unknown): void {\n const initial = initialAttribute(el, name);\n writeAttribute(el, name, value === undefined ? initial : value ? \"\" : null);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\nimport { UploadCore } from \"../core/UploadCore.js\";\nimport { WcsIoErrorInfo } from \"../core/platformCapability.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\nimport { upgradeProperties } from \"../protocol/upgradeProperties.js\";\nimport { reflectAttribute, reflectBooleanAttribute } from \"../protocol/inputAttribute.js\";\n\nexport class WcsUpload extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...UploadCore.wcBindable,\n properties: [\n ...UploadCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\", semantics: \"state\" },\n { name: \"files\", event: \"wcs-upload:files-changed\", semantics: \"state\" },\n ],\n // Shell-level input surface. The Core declares only the portable `url` / `method` /\n // `fieldName`; the Shell adds the DOM-driven settable surface. No `attribute` hints\n // are given: the `url` / `method` / `fieldName` / `multiple` / `maxSize` / `accept` /\n // `manual` setters reflect to their attributes themselves, and a binding system that\n // mirrored inputs[].attribute (@wcstack/state 3.x) would set the attribute twice\n // (`files` / `trigger` are not attribute-backed). `commands` (upload / abort) are inherited unchanged from the\n // Core via the spread above.\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n { name: \"multiple\" },\n { name: \"maxSize\" },\n { name: \"accept\" },\n { name: \"manual\" },\n { name: \"files\" },\n { name: \"trigger\" },\n ],\n };\n // `url` を観測するのは、url の無いうちに自動送信の files を受けたとき、url が来たらその\n // files を送るため(4.5 までは url を待たずに黙って何もしなかった。JSX の props や data-wcs の\n // 束縛は書いた順に当たるので、files を url より前に書くと送られなかった — docs/seam-apps.md、\n // state-field-report と fw-inventory)。それ以外の url の変更では送らない。\n static get observedAttributes(): string[] { return [\"url\"]; }\n\n private _core: UploadCore;\n private _files: FileList | File[] | null = null;\n private _trigger: boolean = false;\n // The reasons `[wcs/command-not-ready]` was said for, once each per element\n // (docs/v4-direction-2026-10.md §5.1, the I/O command policy).\n private _told: Set<string> | null = null;\n // automatic-mode files assigned while there was no url: sent when the url arrives\n private _waitingForUrl = false;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new UploadCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-upload:loading-changed\": (d) => ({ loading: d === true }),\n \"wcs-upload:error\": (d) => ({ error: d != null }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n //\n // setter は null / undefined を setAttribute に文字列化させない(\"undefined\" の url へ\n // 送信したり、\"null\" の method を使ったりしないため)。`null` は属性を外して既定値に戻し、\n // `undefined` は要素が最初に持っていた属性へ戻す(wc-bindable producer guidance P1。\n // React 19 や直接の代入は undefined を書く。@wcstack/state は書かない)。\n\n get url(): string {\n return this.getAttribute(\"url\") || \"\";\n }\n\n set url(value: string | null | undefined) {\n reflectAttribute(this, \"url\", value);\n }\n\n get method(): string {\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\n }\n\n set method(value: string | null | undefined) {\n reflectAttribute(this, \"method\", value);\n }\n\n get fieldName(): string {\n return this.getAttribute(\"field-name\") || \"file\";\n }\n\n set fieldName(value: string | null | undefined) {\n reflectAttribute(this, \"field-name\", value);\n }\n\n get multiple(): boolean {\n return this.hasAttribute(\"multiple\");\n }\n\n set multiple(value: boolean | null | undefined) {\n reflectBooleanAttribute(this, \"multiple\", value);\n }\n\n get maxSize(): number {\n const attr = this.getAttribute(\"max-size\");\n if (attr === null) {\n return Infinity;\n }\n // 不正値(NaN になる \"abc\" など)や負数は「制限なし」(Infinity) として扱う。\n // NaN を返すと `size > NaN` が常に false になりサイズ検証が無言で無効化され、\n // 負数を返すと全ファイルが拒否されるため、いずれも安全側の Infinity に丸める。\n const n = parseInt(attr, 10);\n return Number.isFinite(n) && n >= 0 ? n : Infinity;\n }\n\n set maxSize(value: number | null | undefined) {\n reflectAttribute(this, \"max-size\", value);\n }\n\n get accept(): string {\n return this.getAttribute(\"accept\") || \"\";\n }\n\n set accept(value: string | null | undefined) {\n reflectAttribute(this, \"accept\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean | null | undefined) {\n reflectBooleanAttribute(this, \"manual\", value);\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get progress(): number {\n return this._core.progress;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get status(): number {\n return this._core.status;\n }\n\n get errorInfo(): WcsIoErrorInfo | null {\n return this._core.errorInfo;\n }\n\n get promise(): Promise<any> {\n return this._core.promise;\n }\n\n // --- Command properties ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // 進行中に再度 trigger=true が来ても再入ガードはしない(FetchCore シェルと同一)。\n // upload() → _core.upload() が先頭で既存リクエストを abort し新規開始するため、\n // 連続トリガは「前回を中止して新しいアップロードを開始する」挙動になる。\n // 各 upload() の settle ごとに trigger-changed(false) が 1 回発火する。\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.upload().finally(() => {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n });\n }\n }\n\n get files(): FileList | File[] | null {\n return this._files;\n }\n\n set files(value: FileList | File[] | null | undefined) {\n // undefined は「値が無い」= 初期状態(null)。null と同じく files をクリアし、\n // files-changed にも undefined ではなく null を載せる。\n const files = value ?? null;\n this._files = files;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: files,\n bubbles: true,\n }));\n // files that arrive before the url wait for it (automatic mode only)\n this._waitingForUrl = !this.manual && !!files && files.length > 0 && !this.url;\n if (!this.manual && files && files.length > 0 && this.url) this.upload();\n }\n\n // --- Validation ---\n\n private _validate(files: FileList | File[]): WcsUploadError | null {\n const maxSize = this.maxSize;\n if (maxSize !== Infinity) {\n for (let i = 0; i < files.length; i++) {\n if (files[i].size > maxSize) {\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\n }\n }\n }\n\n const accept = this.accept;\n if (accept) {\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const fileType = file.type.toLowerCase();\n const fileName = file.name.toLowerCase();\n // file.type が空文字(OS が MIME を判定できないファイル)の場合、MIME 系\n // パターン(`image/*` / 厳密 MIME)は一致しない。その場合でも accept に\n // 拡張子パターン(`.pdf` 等)が含まれ拡張子が一致すれば受理される。\n // accept が MIME 系のみのときは型を確認できないため拒否する(安全側)。\n const matched = acceptList.some(pattern => {\n if (pattern.startsWith(\".\")) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith(\"/*\")) {\n return fileType !== \"\" && fileType.startsWith(pattern.slice(0, -1));\n }\n return fileType !== \"\" && fileType === pattern;\n });\n if (!matched) {\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\n }\n }\n }\n\n return null;\n }\n\n // --- Public methods ---\n\n abort(): void {\n this._core.abort();\n }\n\n async upload(): Promise<any> {\n const files = this._files;\n // url 未設定は no-op(null)。Core は never-throw(url 空なら error プロパティに\n // 載せて null を返す)だが、Shell は url/files のライフサイクルを所有しており\n // 「送信先が無い」を「ファイル無し」と同じ無操作として扱い、Core を呼ぶ前に return する。\n // これにより set trigger / set files の fire-and-forget 経路で unhandled rejection が\n // 発生せず、README の「upload() は全終了ケースで resolve し never reject」契約とも整合する。\n if (!files || files.length === 0 || !this.url) {\n this._warnNotReady(!this.url ? \"there is no url\" : \"there are no files\");\n return null;\n }\n\n const validationError = this._validate(files);\n if (validationError) {\n // Route through the Core so `el.error` (which reads _core.error) reflects\n // the validation failure and stays sticky until the next successful upload,\n // matching the family-wide error contract. The Core dispatches\n // wcs-upload:error on this element (its _target), so the observable event is\n // unchanged.\n this._core.setError(validationError);\n return null;\n }\n\n const result = await this._core.upload(this.url, files, {\n method: this.method,\n fieldName: this.fieldName,\n });\n\n // 自分が開始したアップロードのファイルだけをリセット\n // (途中で新しい files がセットされていたら触らない)\n if (this._files === files) {\n this._files = null;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: null,\n bubbles: true,\n }));\n }\n\n return result;\n }\n\n // A refused upload sent nothing and said nothing (no `error`, by design): a `trigger`\n // written before `url` / `files` (`data-wcs` bindings and a framework's props are applied in\n // the order written), a retry after the files were used up.\n private _warnNotReady(reason: string): void {\n if (this._told?.has(reason)) return;\n (this._told ??= new Set()).add(reason);\n console.warn(\n `[@wcstack/upload] [wcs/command-not-ready] The upload was refused: ${reason}, so nothing is sent. ` +\n \"Write url and files before trigger (data-wcs bindings and a framework's props are applied in the order \" +\n \"written), and assign files again for each retry: an upload uses them up. (Said once per element and reason.)\",\n this,\n );\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(_name: string, _oldValue: string | null, newValue: string | null): void {\n // url だけの変更では送らない。url の無いうちに受けた自動送信の files は、url が来たら送る。\n // 接続は問わない: React 19 は要素を文書に入れる前に props を当てる(files の setter も、url が\n // あれば接続の前に送る)。\n if (!this._waitingForUrl || !newValue || this.manual) return;\n // (waiting means files were assigned and not replaced since: the setter resets it)\n this._waitingForUrl = false;\n this.upload();\n }\n\n connectedCallback(): void {\n // upgrade 前に代入された input を取り込み直す(doc 13 §1.2 / Phase A1)\n upgradeProperties(this);\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapUpload(userConfig?: IWritableConfig, registry?: CustomElementRegistry): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents(registry);\n}\n","import { WcsUpload } from \"./components/Upload.js\";\nimport { config } from \"./config.js\";\n\n/**\n * Register this package's tags. Pass a scoped `CustomElementRegistry` to define\n * them for a single shadow tree -- scoped registries do not inherit the global\n * one, so a tree using one needs its own definitions.\n */\nexport function registerComponents(registry: CustomElementRegistry = customElements): void {\n if (!registry.get(config.tagNames.upload)) {\n registry.define(config.tagNames.upload, WcsUpload);\n }\n}\n"],"names":["config","triggerAttribute","tagNames","upload","OperationLane","laneKey","policy","_ownerGeneration","_latestEpoch","_nextOperationId","_activeOperationId","undefined","_activeOperationIds","Set","_queue","_inFlightCount","_terminal","Map","_claimedOutcome","_controllers","_attempts","_withSignal","_trace","constructor","options","this","withSignal","trace","ownerGeneration","inFlightCount","latestEpoch","activeOperationId","begin","supersedeEpoch","_abortController","operationId","ticket","push","add","set","attempt","_makeAttempt","type","retry","has","previous","get","attemptNo","_releaseController","canCommit","status","_isEligible","claimTerminal","outcome","claimedOutcome","finalize","delete","_advanceBookkeeping","signalOf","signal","abort","abortActive","disposeOwner","Array","from","keys","clear","length","AbortController","controller","remaining","filter","t","aborted","assessCapabilities","registry","availability","evaluate","id","spec","probe","requiredAllAvailable","required","a","optionalAllAvailable","optional","readiness","allIds","needsSecure","some","requiresSecureContext","needsActivation","requiresUserActivation","secureContext","globalThis","isSecureContext","userActivation","permission","activity","preconditions","epoch","lastError","requiredCapabilitiesAvailable","assessment","every","WCS_UPLOAD_ERROR_CODE","UPLOAD_CAPABILITIES","XMLHttpRequest","compatKey","UploadCore","EventTarget","static","protocol","version","properties","name","event","semantics","getter","e","detail","value","inputs","commands","async","_target","_value","_loading","_progress","_error","_status","_errorInfo","_xhr","_promise","Promise","resolve","_lane","_ready","target","super","ready","observe","dispose","_setLoading","loading","progress","error","promise","errorInfo","supported","platformAssessment","REQUIRED_CAPABILITIES","_commitStep","step","dispatchEvent","CustomEvent","bubbles","_setProgress","_setError","setError","_setResponse","_setErrorInfo","code","phase","recoverable","message","capabilityId","_commitErrorInfo","info","url","files","p","_doUpload","missing","find","started","method","headers","fieldName","formData","FormData","i","append","xhr","addEventListener","lengthComputable","Math","round","loaded","total","responseText","getResponseHeader","includes","JSON","parse","statusText","body","open","Object","entries","setRequestHeader","send","registered","handleClick","Element","triggerElement","closest","uploadId","getAttribute","UploadCtor","customElements","el","document","getElementById","uploadElement","preventDefault","hasAccessorOnPrototype","proto","getPrototypeOf","descriptor","getOwnPropertyDescriptor","toldObjectAttribute","WeakSet","warnObjectAttribute","element","tag","localName","console","warn","initialAttributes","WeakMap","initialAttribute","byName","writeAttribute","removeAttribute","setAttribute","reflectAttribute","initial","String","reflectBooleanAttribute","WcsUpload","HTMLElement","wcBindable","observedAttributes","_core","_files","_trigger","_told","_waitingForUrl","_connectedCallbackPromise","_internals","_initInternals","_wireStates","d","debugStates","states","attachInternals","internals","map","toStates","debug","hasAttribute","on","toggleAttribute","connectedCallbackPromise","toUpperCase","multiple","maxSize","attr","Infinity","n","parseInt","Number","isFinite","accept","manual","trigger","finally","_validate","size","acceptList","split","s","trim","toLowerCase","file","fileType","fileName","pattern","startsWith","endsWith","slice","_warnNotReady","validationError","result","reason","attributeChangedCallback","_name","_oldValue","newValue","connectedCallback","declaration","input","attribute","call","prototype","hasOwnProperty","record","upgradeProperties","style","display","disconnectedCallback","define","registerComponents"],"mappings":"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"}
|