@peter.naydenov/walk-async 3.1.0 → 3.1.2

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/Changelog.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
 
4
4
 
5
+ ### 3.1.2 (2026-07-19)
6
+ - [x] Fix: built-in object types whose data lives outside the own-enumerable-string-key model (`Date`, `RegExp`, `Map`, `Set`, `WeakMap`, `WeakSet`, `ArrayBuffer`, `DataView`, and all `TypedArray` subclasses) used to be classified as a plain `object` by `findType` and ended up as an empty `{}` in the result. They are now classified as `simple` and preserved by reference, matching the contract already used for `function` values and DOM nodes. Note: this changes the observable shape of the result when a property holds one of these types — the value is now the same reference as the input, not a plain-object copy;
7
+ - [x] Fix: the per-key `finishWithCallbacks` task (and, for the `objectCallback` path, the `keyCallbackTask`) was left unresolved when a callback called `reject()` to skip the key. The walk still completed because the outer `executeCallback` was signalled, but the internal tasks lingered. Both now resolve on the `IGNORE` paths so nothing leaks. Note: behavior of the walk itself is unchanged — these are the same outcomes, just with a clean chain;
8
+
9
+
10
+
11
+ ### 3.1.1 (2026-07-12)
12
+ - [x] Moving to typescript v.7.x.x;
13
+ - [x] Changing 'mocha' testing library with vitest;
14
+ - [x] Converting all tests to vitest;
15
+ - [x] Changing coverage library from c8 to @vitest/coverage-v8;
16
+
17
+
18
+
5
19
  ### 3.1.0 (2026-07-07)
6
20
  - [x] New option 'timeout'. Milliseconds. When set, the walk promise is rejected if callbacks do not resolve in time. Error message lists the breadcrumbs of the pending callbacks;
7
21
 
@@ -1 +1 @@
1
- "use strict";var e=require("ask-for-promise");async function o(e,o,n){for await(const o of e)await o.next();n.done(o)}function n(e){return null==e||e.nodeType?"simple":e instanceof Array?"array":"object"==typeof e?"object":"simple"}async function*r(e,o,n,r,s,a){yield await t(e,o,n,r,s,...a)}function t(o,t,s,a,i,...c){let[l,d]=a,p=Object.keys(o),u=e(p),f=e();return p.forEach((p,f)=>{let m=n(o[p]),y=o[p],$="simple"!==m&&null!=d,b=e(),k=e(),h=e(),j="array"===n(t),v=!isNaN(p),C=Symbol("ignore___"),w="root"===i&&"root"===p,N=w?"root":`${i}/${p}`;$?d({resolve:b.done,reject:()=>b.done(C),value:y,key:p,breadcrumbs:N},...c):b.done("$$cancel"),b.onComplete(e=>{if("$$cancel"!==e||l)if("$$cancel"!==e&&(y=e,m=n(y)),y!=C)if("simple"===m){if(!l)return void k.done("$$noUpdates");l({resolve:k.done,reject:()=>k.done(C),value:y,key:p,breadcrumbs:N},...c)}else k.done("$$cancel");else u.promises[f].done("ignore object");else k.done("$$noUpdates")}),k.onComplete(e=>{if(w)return s.push(r(y,t,s,a,"root",c)),void u.promises[f].done("root");if(e!=C)if("$$cancel"!==e){if("$$noUpdates"!==e&&(y=e,m=n(y)),"simple"===m){const e=function(e,o){return o instanceof Array&&!isNaN(e)}(p,t);return e?t.push(y):t[p]=y,void u.promises[f].done("key")}h.done()}else h.done();else u.promises[f].done("ignore key")}),h.onComplete(()=>{if("object"===m){const e={};j&&v?t.push(e):t[p]=e,s.push(r(y,e,s,a,N,c)),u.promises[f].done("object")}if("array"===m){const e=[];j&&v?t.push(e):t[p]=e,s.push(r(y,e,s,a,N,c)),u.promises[f].done("array")}})}),u.onComplete(e=>f.done()),f.promise}module.exports=function({data:r,objectCallback:s=null,keyCallback:a=null},...i){let c,l=n(r),d=[],p="root",u=[a,s],f=e();switch(l){case"array":c=[],t({root:r},c,d,u,p,...i).then(()=>o(d,c,f));break;case"object":c={},t({root:r},c,d,u,p,...i).then(()=>{o(d,c,f)});break;case"simple":f.done(r)}return f.promise};
1
+ "use strict";var e=require("ask-for-promise");async function o(e,o,n){for await(const o of e)await o.next();n.done(o)}function n(e){return null==e||e.nodeType?"simple":e instanceof Array?"array":"object"==typeof e?e instanceof Date||e instanceof RegExp||e instanceof Map||e instanceof Set||e instanceof WeakMap||e instanceof WeakSet||e instanceof ArrayBuffer||e instanceof DataView||ArrayBuffer.isView(e)?"simple":"object":"simple"}async function*t(e,o,n,t,a,i){yield await r(e,o,n,t,a,...i)}function a(e,o,n){"__proto__"===o?Object.defineProperty(e,o,{value:n,enumerable:!0,writable:!0,configurable:!0}):e[o]=n}function r(o,r,i,l,s,...c){let[d,u,p]=l,f=Object.keys(o),m=e(f),b=e();return f.forEach((f,b)=>{let y=n(o[f]),$=o[f],k="simple"!==y&&null!=u,j=e(),v=e(),_=e(),C="array"===n(r),w=!isNaN(f),h=Symbol("ignore___"),g=`${s}/${f}`,S=`objectCallback at '${g}'`,x=`keyCallback at '${g}'`;k?(p.add(S),u({resolve:j.done,reject:()=>j.done(h),value:$,key:f,breadcrumbs:g},...c)):j.done("$$cancel"),j.onComplete(e=>{if(p.delete(S),"$$cancel"!==e||d){if("$$cancel"!==e&&($=e,y=n($)),$==h)return m.promises[b].done("ignore object"),v.done("$$cancel"),void _.done();if("simple"===y){if(!d)return void v.done("$$noUpdates");p.add(x),d({resolve:v.done,reject:()=>v.done(h),value:$,key:f,breadcrumbs:g},...c)}else v.done("$$cancel")}else v.done("$$noUpdates")}),v.onComplete(e=>{if(p.delete(x),e==h)return m.promises[b].done("ignore key"),void _.done();if("$$cancel"!==e){if("$$noUpdates"!==e&&($=e,y=n($)),"simple"===y){const e=function(e,o){return o instanceof Array&&!isNaN(e)}(f,r);return e?r.push($):a(r,f,$),void m.promises[b].done("key")}_.done()}else _.done()}),_.onComplete(()=>{if("object"===y){const e={};C&&w?r.push(e):a(r,f,e),i.push(t($,e,i,l,g,c)),m.promises[b].done("object")}if("array"===y){const e=[];C&&w?r.push(e):a(r,f,e),i.push(t($,e,i,l,g,c)),m.promises[b].done("array")}})}),m.onComplete(e=>b.done()),b.promise}module.exports=function({data:t,objectCallback:a=null,keyCallback:i=null,timeout:l=null},...s){let c,d=n(t),u=[],p="root",f=new Set,m=[i,a,f],b=e(),y=e(),$=Symbol("ignore___");if("simple"!==d&&a?(f.add("objectCallback at 'root'"),a({resolve:y.done,reject:()=>y.done($),value:t,key:"root",breadcrumbs:p},...s)):y.done(t),y.onComplete(e=>{if(f.delete("objectCallback at 'root'"),e!==$)switch(n(e)){case"array":c=[],r(e,c,u,m,p,...s).then(()=>o(u,c,b));break;case"object":c={},r(e,c,u,m,p,...s).then(()=>{o(u,c,b)});break;case"simple":b.done(e)}else b.done("array"===d?[]:{})}),null==l)return b.promise;const k=Symbol("expired___"),j=e();return b.timeout(l,k),b.onComplete(e=>{if(e!==k)return void j.done(e);const o=[...f].map(e=>`\n - ${e}`).join("");j.cancel(new Error(`walk-async: timed out after ${l}ms; callbacks still pending:${o}`))}),j.promise};
@@ -1 +1 @@
1
- import e from"ask-for-promise";function o({data:o,objectCallback:t=null,keyCallback:a=null},...i){let c,l=r(o),p=[],d="root",u=[a,t],f=e();switch(l){case"array":c=[],s({root:o},c,p,u,d,...i).then(()=>n(p,c,f));break;case"object":c={},s({root:o},c,p,u,d,...i).then(()=>{n(p,c,f)});break;case"simple":f.done(o)}return f.promise}async function n(e,o,n){for await(const o of e)await o.next();n.done(o)}function r(e){return null==e||e.nodeType?"simple":e instanceof Array?"array":"object"==typeof e?"object":"simple"}async function*t(e,o,n,r,t,a){yield await s(e,o,n,r,t,...a)}function s(o,n,s,a,i,...c){let[l,p]=a,d=Object.keys(o),u=e(d),f=e();return d.forEach((d,f)=>{let m=r(o[d]),y=o[d],$="simple"!==m&&null!=p,b=e(),k=e(),h=e(),j="array"===r(n),v=!isNaN(d),C=Symbol("ignore___"),w="root"===i&&"root"===d,N=w?"root":`${i}/${d}`;$?p({resolve:b.done,reject:()=>b.done(C),value:y,key:d,breadcrumbs:N},...c):b.done("$$cancel"),b.onComplete(e=>{if("$$cancel"!==e||l)if("$$cancel"!==e&&(y=e,m=r(y)),y!=C)if("simple"===m){if(!l)return void k.done("$$noUpdates");l({resolve:k.done,reject:()=>k.done(C),value:y,key:d,breadcrumbs:N},...c)}else k.done("$$cancel");else u.promises[f].done("ignore object");else k.done("$$noUpdates")}),k.onComplete(e=>{if(w)return s.push(t(y,n,s,a,"root",c)),void u.promises[f].done("root");if(e!=C)if("$$cancel"!==e){if("$$noUpdates"!==e&&(y=e,m=r(y)),"simple"===m){const e=function(e,o){return o instanceof Array&&!isNaN(e)}(d,n);return e?n.push(y):n[d]=y,void u.promises[f].done("key")}h.done()}else h.done();else u.promises[f].done("ignore key")}),h.onComplete(()=>{if("object"===m){const e={};j&&v?n.push(e):n[d]=e,s.push(t(y,e,s,a,N,c)),u.promises[f].done("object")}if("array"===m){const e=[];j&&v?n.push(e):n[d]=e,s.push(t(y,e,s,a,N,c)),u.promises[f].done("array")}})}),u.onComplete(e=>f.done()),f.promise}export{o as default};
1
+ import e from"ask-for-promise";function o({data:o,objectCallback:t=null,keyCallback:r=null,timeout:l=null},...c){let s,d=a(o),f=[],p="root",u=new Set,m=[r,t,u],b=e(),y=e(),$=Symbol("ignore___");if("simple"!==d&&t?(u.add("objectCallback at 'root'"),t({resolve:y.done,reject:()=>y.done($),value:o,key:"root",breadcrumbs:p},...c)):y.done(o),y.onComplete(e=>{if(u.delete("objectCallback at 'root'"),e!==$)switch(a(e)){case"array":s=[],i(e,s,f,m,p,...c).then(()=>n(f,s,b));break;case"object":s={},i(e,s,f,m,p,...c).then(()=>{n(f,s,b)});break;case"simple":b.done(e)}else b.done("array"===d?[]:{})}),null==l)return b.promise;const k=Symbol("expired___"),j=e();return b.timeout(l,k),b.onComplete(e=>{if(e!==k)return void j.done(e);const o=[...u].map(e=>`\n - ${e}`).join("");j.cancel(new Error(`walk-async: timed out after ${l}ms; callbacks still pending:${o}`))}),j.promise}async function n(e,o,n){for await(const o of e)await o.next();n.done(o)}function a(e){return null==e||e.nodeType?"simple":e instanceof Array?"array":"object"==typeof e?e instanceof Date||e instanceof RegExp||e instanceof Map||e instanceof Set||e instanceof WeakMap||e instanceof WeakSet||e instanceof ArrayBuffer||e instanceof DataView||ArrayBuffer.isView(e)?"simple":"object":"simple"}async function*t(e,o,n,a,t,r){yield await i(e,o,n,a,t,...r)}function r(e,o,n){"__proto__"===o?Object.defineProperty(e,o,{value:n,enumerable:!0,writable:!0,configurable:!0}):e[o]=n}function i(o,n,i,l,c,...s){let[d,f,p]=l,u=Object.keys(o),m=e(u),b=e();return u.forEach((u,b)=>{let y=a(o[u]),$=o[u],k="simple"!==y&&null!=f,j=e(),_=e(),v=e(),C="array"===a(n),w=!isNaN(u),h=Symbol("ignore___"),g=`${c}/${u}`,S=`objectCallback at '${g}'`,x=`keyCallback at '${g}'`;k?(p.add(S),f({resolve:j.done,reject:()=>j.done(h),value:$,key:u,breadcrumbs:g},...s)):j.done("$$cancel"),j.onComplete(e=>{if(p.delete(S),"$$cancel"!==e||d){if("$$cancel"!==e&&($=e,y=a($)),$==h)return m.promises[b].done("ignore object"),_.done("$$cancel"),void v.done();if("simple"===y){if(!d)return void _.done("$$noUpdates");p.add(x),d({resolve:_.done,reject:()=>_.done(h),value:$,key:u,breadcrumbs:g},...s)}else _.done("$$cancel")}else _.done("$$noUpdates")}),_.onComplete(e=>{if(p.delete(x),e==h)return m.promises[b].done("ignore key"),void v.done();if("$$cancel"!==e){if("$$noUpdates"!==e&&($=e,y=a($)),"simple"===y){const e=function(e,o){return o instanceof Array&&!isNaN(e)}(u,n);return e?n.push($):r(n,u,$),void m.promises[b].done("key")}v.done()}else v.done()}),v.onComplete(()=>{if("object"===y){const e={};C&&w?n.push(e):r(n,u,e),i.push(t($,e,i,l,g,s)),m.promises[b].done("object")}if("array"===y){const e=[];C&&w?n.push(e):r(n,u,e),i.push(t($,e,i,l,g,s)),m.promises[b].done("array")}})}),m.onComplete(e=>b.done()),b.promise}export{o as default};
@@ -1 +1 @@
1
- !function(e,o){"object"==typeof exports&&"undefined"!=typeof module?module.exports=o(require("ask-for-promise")):"function"==typeof define&&define.amd?define(["ask-for-promise"],o):(e="undefined"!=typeof globalThis?globalThis:e||self).walkAsync=o(e.askForPromise)}(this,function(e){"use strict";async function o(e,o,n){for await(const o of e)await o.next();n.done(o)}function n(e){return null==e||e.nodeType?"simple":e instanceof Array?"array":"object"==typeof e?"object":"simple"}async function*r(e,o,n,r,s,i){yield await t(e,o,n,r,s,...i)}function t(o,t,s,i,a,...c){let[l,d]=i,f=Object.keys(o),p=e(f),u=e();return f.forEach((f,u)=>{let m=n(o[f]),y=o[f],b="simple"!==m&&null!=d,$=e(),k=e(),h=e(),j="array"===n(t),v=!isNaN(f),C=Symbol("ignore___"),g="root"===a&&"root"===f,w=g?"root":`${a}/${f}`;b?d({resolve:$.done,reject:()=>$.done(C),value:y,key:f,breadcrumbs:w},...c):$.done("$$cancel"),$.onComplete(e=>{if("$$cancel"!==e||l)if("$$cancel"!==e&&(y=e,m=n(y)),y!=C)if("simple"===m){if(!l)return void k.done("$$noUpdates");l({resolve:k.done,reject:()=>k.done(C),value:y,key:f,breadcrumbs:w},...c)}else k.done("$$cancel");else p.promises[u].done("ignore object");else k.done("$$noUpdates")}),k.onComplete(e=>{if(g)return s.push(r(y,t,s,i,"root",c)),void p.promises[u].done("root");if(e!=C)if("$$cancel"!==e){if("$$noUpdates"!==e&&(y=e,m=n(y)),"simple"===m){const e=function(e,o){return o instanceof Array&&!isNaN(e)}(f,t);return e?t.push(y):t[f]=y,void p.promises[u].done("key")}h.done()}else h.done();else p.promises[u].done("ignore key")}),h.onComplete(()=>{if("object"===m){const e={};j&&v?t.push(e):t[f]=e,s.push(r(y,e,s,i,w,c)),p.promises[u].done("object")}if("array"===m){const e=[];j&&v?t.push(e):t[f]=e,s.push(r(y,e,s,i,w,c)),p.promises[u].done("array")}})}),p.onComplete(e=>u.done()),u.promise}return function({data:r,objectCallback:s=null,keyCallback:i=null},...a){let c,l=n(r),d=[],f="root",p=[i,s],u=e();switch(l){case"array":c=[],t({root:r},c,d,p,f,...a).then(()=>o(d,c,u));break;case"object":c={},t({root:r},c,d,p,f,...a).then(()=>{o(d,c,u)});break;case"simple":u.done(r)}return u.promise}});
1
+ !function(e,o){"object"==typeof exports&&"undefined"!=typeof module?module.exports=o(require("ask-for-promise")):"function"==typeof define&&define.amd?define(["ask-for-promise"],o):(e="undefined"!=typeof globalThis?globalThis:e||self).walkAsync=o(e.askForPromise)}(this,function(e){"use strict";async function o(e,o,n){for await(const o of e)await o.next();n.done(o)}function n(e){return null==e||e.nodeType?"simple":e instanceof Array?"array":"object"==typeof e?e instanceof Date||e instanceof RegExp||e instanceof Map||e instanceof Set||e instanceof WeakMap||e instanceof WeakSet||e instanceof ArrayBuffer||e instanceof DataView||ArrayBuffer.isView(e)?"simple":"object":"simple"}async function*t(e,o,n,t,a,i){yield await r(e,o,n,t,a,...i)}function a(e,o,n){"__proto__"===o?Object.defineProperty(e,o,{value:n,enumerable:!0,writable:!0,configurable:!0}):e[o]=n}function r(o,r,i,s,l,...c){let[d,f,u]=s,p=Object.keys(o),m=e(p),b=e();return p.forEach((p,b)=>{let y=n(o[p]),$=o[p],k="simple"!==y&&null!=f,j=e(),_=e(),h=e(),v="array"===n(r),C=!isNaN(p),w=Symbol("ignore___"),g=`${l}/${p}`,S=`objectCallback at '${g}'`,x=`keyCallback at '${g}'`;k?(u.add(S),f({resolve:j.done,reject:()=>j.done(w),value:$,key:p,breadcrumbs:g},...c)):j.done("$$cancel"),j.onComplete(e=>{if(u.delete(S),"$$cancel"!==e||d){if("$$cancel"!==e&&($=e,y=n($)),$==w)return m.promises[b].done("ignore object"),_.done("$$cancel"),void h.done();if("simple"===y){if(!d)return void _.done("$$noUpdates");u.add(x),d({resolve:_.done,reject:()=>_.done(w),value:$,key:p,breadcrumbs:g},...c)}else _.done("$$cancel")}else _.done("$$noUpdates")}),_.onComplete(e=>{if(u.delete(x),e==w)return m.promises[b].done("ignore key"),void h.done();if("$$cancel"!==e){if("$$noUpdates"!==e&&($=e,y=n($)),"simple"===y){const e=function(e,o){return o instanceof Array&&!isNaN(e)}(p,r);return e?r.push($):a(r,p,$),void m.promises[b].done("key")}h.done()}else h.done()}),h.onComplete(()=>{if("object"===y){const e={};v&&C?r.push(e):a(r,p,e),i.push(t($,e,i,s,g,c)),m.promises[b].done("object")}if("array"===y){const e=[];v&&C?r.push(e):a(r,p,e),i.push(t($,e,i,s,g,c)),m.promises[b].done("array")}})}),m.onComplete(e=>b.done()),b.promise}return function({data:t,objectCallback:a=null,keyCallback:i=null,timeout:s=null},...l){let c,d=n(t),f=[],u="root",p=new Set,m=[i,a,p],b=e(),y=e(),$=Symbol("ignore___");if("simple"!==d&&a?(p.add("objectCallback at 'root'"),a({resolve:y.done,reject:()=>y.done($),value:t,key:"root",breadcrumbs:u},...l)):y.done(t),y.onComplete(e=>{if(p.delete("objectCallback at 'root'"),e!==$)switch(n(e)){case"array":c=[],r(e,c,f,m,u,...l).then(()=>o(f,c,b));break;case"object":c={},r(e,c,f,m,u,...l).then(()=>{o(f,c,b)});break;case"simple":b.done(e)}else b.done("array"===d?[]:{})}),null==s)return b.promise;const k=Symbol("expired___"),j=e();return b.timeout(s,k),b.onComplete(e=>{if(e!==k)return void j.done(e);const o=[...p].map(e=>`\n - ${e}`).join("");j.cancel(new Error(`walk-async: timed out after ${s}ms; callbacks still pending:${o}`))}),j.promise}});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peter.naydenov/walk-async",
3
- "version": "3.1.0",
3
+ "version": "3.1.2",
4
4
  "description": "Deep copy with fine control during the process. Can be used also as a deep forEach function",
5
5
  "main": ".dist/walk-async.umd.js",
6
6
  "type": "module",
@@ -16,8 +16,9 @@
16
16
  "./src/*": "./src/*"
17
17
  },
18
18
  "scripts": {
19
- "test": "mocha test",
20
- "cover": "c8 mocha test",
19
+ "test": "vitest run",
20
+ "test:watch": "vitest",
21
+ "cover": "vitest run --coverage",
21
22
  "build": "rollup -c",
22
23
  "postbuild": "tsc -p tsconfig.json"
23
24
  },
@@ -34,29 +35,27 @@
34
35
  "@rollup/plugin-commonjs": "^29.0.3",
35
36
  "@rollup/plugin-node-resolve": "^16.0.3",
36
37
  "@rollup/plugin-terser": "^1.0.0",
37
- "c8": "^11.0.0",
38
- "chai": "^6.2.2",
39
- "mocha": "^11.7.6",
38
+ "@vitest/coverage-v8": "4.1.10",
40
39
  "rollup": "^4.62.2",
41
- "typescript": "^6.0.3"
40
+ "typescript": "^7.0.2",
41
+ "vite": "^8.1.4",
42
+ "vitest": "4.1.10"
42
43
  },
43
- "overrides": {
44
- "diff": "^8.0.2",
45
- "serialize-javascript": "^7.0.0"
46
- },
47
- "c8": {
48
- "include": [
49
- "src/**/*.js"
50
- ],
51
- "exclude": [
52
- "node_modules",
53
- "test",
54
- "test-data"
55
- ],
56
- "reporter": [
57
- "lcov",
58
- "text-summary"
59
- ]
44
+ "vitest": {
45
+ "coverage": {
46
+ "include": [
47
+ "src/**/*.js"
48
+ ],
49
+ "exclude": [
50
+ "node_modules",
51
+ "test",
52
+ "test-data"
53
+ ],
54
+ "reporter": [
55
+ "lcov",
56
+ "text-summary"
57
+ ]
58
+ }
60
59
  },
61
60
  "browserslist": "> 2%, not dead",
62
61
  "allowScripts": {
package/src/main.js CHANGED
@@ -124,8 +124,22 @@ function findType ( x ) {
124
124
  if ( x == null ) return 'simple' // null and undefined
125
125
  if ( x.nodeType ) return 'simple' // DOM node
126
126
  if ( x instanceof Array ) return 'array'
127
- if ( typeof x === 'object' ) return 'object'
128
- return 'simple' // number, bigint, string, boolean, symbol, function
127
+ if ( typeof x === 'object' ) {
128
+ // Built-in object types whose data lives outside the own-enumerable-string-key
129
+ // model that walk uses. Treated as 'simple' so the value is preserved by
130
+ // reference (same contract as functions and DOM nodes).
131
+ if ( x instanceof Date ) return 'simple'
132
+ if ( x instanceof RegExp ) return 'simple'
133
+ if ( x instanceof Map ) return 'simple'
134
+ if ( x instanceof Set ) return 'simple'
135
+ if ( x instanceof WeakMap ) return 'simple'
136
+ if ( x instanceof WeakSet ) return 'simple'
137
+ if ( x instanceof ArrayBuffer ) return 'simple'
138
+ if ( x instanceof DataView ) return 'simple'
139
+ if ( ArrayBuffer.isView ( x ) ) return 'simple' // Typed arrays (Uint8Array, Float32Array, ...)
140
+ return 'object'
141
+ }
142
+ return 'simple' // number, bigint, string, boolean, symbol, function
129
143
  } // findType func.
130
144
 
131
145
 
@@ -202,10 +216,15 @@ function copyObject ( origin, result, extend, cb, breadcrumbs, ...args ) {
202
216
  item = res
203
217
  type = findType ( item )
204
218
  }
205
- if ( item == IGNORE ) {
219
+ if ( item == IGNORE ) {
220
+ // Object callback rejected this key. Skip the rest of
221
+ // the per-key chain; resolve the remaining tasks so
222
+ // nothing leaks.
206
223
  executeCallback.promises[i].done ( 'ignore object' )
224
+ keyCallbackTask.done ( '$$cancel' )
225
+ finishWithCallbacks.done ()
207
226
  return
208
- }
227
+ }
209
228
  if ( type === 'simple' ) {
210
229
  if ( !keyCallback ) {
211
230
  keyCallbackTask.done ( '$$noUpdates' )
@@ -228,7 +247,10 @@ function copyObject ( origin, result, extend, cb, breadcrumbs, ...args ) {
228
247
  keyCallbackTask.onComplete ( value => {
229
248
  pending.delete ( keyTag )
230
249
  if ( value == IGNORE ) {
250
+ // Key callback rejected this key. Finish the
251
+ // per-key chain so finishWithCallbacks doesn't leak.
231
252
  executeCallback.promises[i].done ( 'ignore key' )
253
+ finishWithCallbacks.done ()
232
254
  return
233
255
  }
234
256
  if ( value === '$$cancel' ) {
package/types/main.d.ts CHANGED
@@ -1,4 +1,16 @@
1
- export default walk;
1
+ /**
2
+ * walk-async
3
+ *
4
+ * Alternative of deep-copy that provides much better control during creation of immutable
5
+ * copies of javascript data structures.
6
+ * Library is using 'generator functions'. If support for old browsers is required,
7
+ * add a polyfill for 'generators'.
8
+ *
9
+ * History notes:
10
+ * - Walk-async was born on September 18th, 2022
11
+ * - Converted to ES module on January 1st, 2024
12
+ *
13
+ */
2
14
  export type Options = {
3
15
  /**
4
16
  * - The data structure to be copied.
@@ -12,12 +24,17 @@ export type Options = {
12
24
  * - A function called for every property in the data structure.
13
25
  */
14
26
  keyCallback: Function | null;
27
+ /**
28
+ * - Milliseconds. When set, the promise is rejected if callbacks do not resolve in time. Error lists the pending callbacks.
29
+ */
30
+ timeout?: number | null;
15
31
  };
16
32
  /**
17
33
  * @typedef {Object} Options
18
34
  * @property {Object} data - The data structure to be copied.
19
35
  * @property {Function|null} objectCallback - A function called for every object in the data structure.
20
36
  * @property {Function|null} keyCallback - A function called for every property in the data structure.
37
+ * @property {number|null} [timeout] - Milliseconds. When set, the promise is rejected if callbacks do not resolve in time. Error lists the pending callbacks.
21
38
  */
22
39
  /**
23
40
  * Walk-async is a deep copy function that executes callback functions on every object and property.
@@ -27,9 +44,11 @@ export type Options = {
27
44
  * - data - The data structure to be copied.
28
45
  * - objectCallback - A function that will be called for every object in the data structure.
29
46
  * - keyCallback - A function that will be called for every property in the data structure.
47
+ * - timeout - Milliseconds. When set, the promise is rejected if callbacks do not resolve in time.
30
48
  * @param {...any} args - Any additional arguments will be passed to the callback functions.
31
49
  *
32
50
  * @returns {Promise} - A promise that resolves to the immutable copy of the data structure.
33
51
  */
34
- declare function walk({ data: origin, objectCallback, keyCallback }: Options, ...args: any[]): Promise<any>;
52
+ declare function walk({ data: origin, objectCallback, keyCallback, timeout }: Options, ...args: any[]): Promise<any>;
53
+ export default walk;
35
54
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.js"],"names":[],"mappings":";;;;;UAoBc,MAAM;;;;oBACN,WAAS,IAAI;;;;iBACb,WAAS,IAAI;;AAJ3B;;;;;GAKG;AAKH;;;;;;;;;;;GAWG;AACH,qEARW,OAAO,WAIJ,GAAG,EAAA,gBAmChB"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.js"],"names":[],"mappings":"AACA;;;;;;;;;;;;GAYG;AAMA,YAAkB,OAAO,GACzB;;;;IAAmB,IAAI,EAAZ,MAAM,CACjB;;;;IAA0B,cAAc,EAA7B,WAAS,IAAI,CACxB;;;;IAA0B,WAAW,EAA1B,WAAS,IAAI,CACxB;;;;IAAyB,OAAO,AAAhC,CACF,EADa,MAAM,GAAC,IAAI,CACxB;CAAA,CAAA;AAND;;;;;;GAMG;AAKH;;;;;;;;;;;;GAYG;AACH,iBAAS,IAAI,CAAE,EACG,IAAI,EAAC,MAAM,EACX,cAAqB,EACrB,WAAkB,EAClB,OAAc,EACnB,EAdF,OAcE,EAAE,GAAG,IAAI,EATR,GAAG,EASK,gBA8DrB;eA4Lc,IAAI"}
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config'
2
+
3
+
4
+ export default defineConfig ({
5
+ test : {
6
+ globals : true
7
+ }
8
+ })