diff --git a/.prettierignore b/.prettierignore index 326da2e..46e39d6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ .prettierrc browser/dist lib/dist -demos/publishers +demos/vanilla/nocookies/targeting/prebid*.js +demos/vanilla/targeting/prebid*.js diff --git a/Dockerfile b/Dockerfile index 0bd80cd..631b25f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,6 +54,15 @@ COPY --from=build /build/demos/vanilla/identify.html ./vanilla/identify.html COPY --from=build /build/demos/vanilla/profile.html ./vanilla/profile.html COPY --from=build /build/demos/vanilla/witness.html ./vanilla/witness.html COPY --from=build /build/demos/vanilla/authenticator.html ./vanilla/authenticator.html +COPY --from=build /build/demos/vanilla/nocookies/targeting/gam360.html ./vanilla/nocookies/targeting/gam360.html +COPY --from=build /build/demos/vanilla/nocookies/targeting/gam360-cached.html ./vanilla/nocookies/targeting/gam360-cached.html +COPY --from=build /build/demos/vanilla/nocookies/targeting/prebid.html ./vanilla/nocookies/targeting/prebid.html +COPY --from=build /build/demos/vanilla/nocookies/targeting/prebid-us-east-16.html ./vanilla/nocookies/targeting/prebid-us-east-16.html +COPY --from=build /build/demos/vanilla/nocookies/targeting/prebid.js ./vanilla/nocookies/targeting/prebid.js +COPY --from=build /build/demos/vanilla/nocookies/targeting/prebid-us-east-16.js ./vanilla/nocookies/targeting/prebid-us-east-16.js +COPY --from=build /build/demos/vanilla/nocookies/identify.html ./vanilla/nocookies/identify.html +COPY --from=build /build/demos/vanilla/nocookies/profile.html ./vanilla/nocookies/profile.html +COPY --from=build /build/demos/vanilla/nocookies/witness.html ./vanilla/nocookies/witness.html COPY --from=build /build/demos/react/dist/ ./react/dist/ COPY --from=build /build/demos/index.html ./index.html COPY --from=build /build/demos/css/ ./css/ diff --git a/README.md b/README.md index 113f67d..19cbe97 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ JavaScript SDK for integrating with optable-sandbox from a web site or web appli - [script tag](#script-tag) - [Versioning](#versioning) - [Domains and Cookies](#domains-and-cookies) + - [LocalStorage](#localstorage) - [Using (npm module)](#using-npm-module) - [Identify API](#identify-api) - [Profile API](#profile-api) @@ -74,6 +75,18 @@ For example, if your website runs at `www.customer.com` or `customer.com`, then > :warning: **Optable Visitor ID Scope**: The _visitor ID_ configured by the Optable sandbox will be unique to a browser only within the top-level domain that the sandbox shares with the calling web site. +### LocalStorage + +In cases where it is not practical or possible to configure your sandbox to run on the same effective top-level domain plus one (eTLD+1) as your website(s), then the default cookie-based transport that the SDK depends on will not work. Instead, a fallback cookie-less transport utilizing browser `LocalStorage` is recommended. To switch to the cookie-less transport, simply set the optional `cookies` parameter to `false` when creating your SDK instance. For example: + +```javascript +import OptableSDK from "@optable/web-sdk"; + +const sdk = new OptableSDK({ host: "sandbox.customer.com", site: "my-site", cookies: false }); +``` + +Note that the default is `cookies: true` and will be inferred if you do not specify the `cookies` parameter at all. + ## Using (npm module) To configure an instance of `OptableSDK` integrating with an [Optable](https://optable.co/) sandbox running at hostname `sandbox.customer.com`, from a configured web site origin identified by slug `my-site`, you simply create an instance of the `OptableSDK` class exported by the `@optable/web-sdk` module: diff --git a/demos/Makefile b/demos/Makefile index 44a26cd..664dabb 100644 --- a/demos/Makefile +++ b/demos/Makefile @@ -12,7 +12,14 @@ html: envsubst < ./vanilla/targeting/gam360-cached.html.tpl > ./vanilla/targeting/gam360-cached.html && \ envsubst < ./vanilla/targeting/prebid.html.tpl > ./vanilla/targeting/prebid.html && \ envsubst < ./vanilla/targeting/prebid-us-east-16.html.tpl > ./vanilla/targeting/prebid-us-east-16.html && \ - envsubst < ./vanilla/authenticator.html.tpl > ./vanilla/authenticator.html + envsubst < ./vanilla/authenticator.html.tpl > ./vanilla/authenticator.html && \ + envsubst < ./vanilla/nocookies/identify.html.tpl > ./vanilla/nocookies/identify.html && \ + envsubst < ./vanilla/nocookies/witness.html.tpl > ./vanilla/nocookies/witness.html && \ + envsubst < ./vanilla/nocookies/profile.html.tpl > ./vanilla/nocookies/profile.html && \ + envsubst < ./vanilla/nocookies/targeting/gam360.html.tpl > ./vanilla/nocookies/targeting/gam360.html && \ + envsubst < ./vanilla/nocookies/targeting/gam360-cached.html.tpl > ./vanilla/nocookies/targeting/gam360-cached.html && \ + envsubst < ./vanilla/nocookies/targeting/prebid.html.tpl > ./vanilla/nocookies/targeting/prebid.html && \ + envsubst < ./vanilla/nocookies/targeting/prebid-us-east-16.html.tpl > ./vanilla/nocookies/targeting/prebid-us-east-16.html .PHONY: react react: diff --git a/demos/index-nocookies.html b/demos/index-nocookies.html new file mode 100644 index 0000000..1e73c4c --- /dev/null +++ b/demos/index-nocookies.html @@ -0,0 +1,110 @@ + + + + + Optable Web SDK Demos + + + + + + + + + +
+
+
+ +
+
+
+
+
+

👋 demo.optable.co (cookies=false)

+

+ To learn about optable-web-sdk integration on your web site or application, see the latest releases, or + report an issue, please check out the + web-sdk GitHub README. If you're looking for more + information on Optable itself, visit our company site. +

+

+ In all examples below, the Optable demo environment is used. Data stored by the demo environment is + periodically deleted. +

+

+ Note that the examples below initialize the OptableSDK with cookies=false, so all ID transport is done + using browser LocalStorage. + Generally, it is preferable to use secure first party HTTP-only cookies for transporting IDs from + OptableSDK. However, when the integrating website does not share the same top-level domain name with the + Optable Sandbox, then first party cookies are not reliable, and the LocalStorage method is suggested. To + enable it, simply initialize the OptableSDK object with the cookies option set to + false, and the SDK will do the rest. +

+
+
+
+
+
Examples
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LinkDescription
identify API + Simple script tag integration showing how to send a hashed Email address and optional + publisher user ID to your sandbox. +
witness APIShows how to log events with optional properties to your sandbox.
profile APIShows how to set visitor traits (e.g., age=45) and sync them to your sandbox.
targeting & GAM360 activation + Shows how to load active cohorts for a visitor and pass them to + Google Ad Manager (GAM) via the + Google Publisher Tag for + ad targeting. +
+ cached targeting & GAM360 activation + + Shows how to load and cache active cohorts in a visitor's browser. Separately, cached cohorts are + passed to Google Ad Manager (GAM) via the + Google Publisher Tag for + ad targeting. +
+
+
+
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + diff --git a/demos/vanilla/nocookies/identify.html b/demos/vanilla/nocookies/identify.html new file mode 100644 index 0000000..b8dbba1 --- /dev/null +++ b/demos/vanilla/nocookies/identify.html @@ -0,0 +1,138 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: identify API

+

+ Simple script tag integration showing how to send a hashed Email address and optional publisher + user ID to your sandbox. +

+
+
+ +
+
+
+
+ + +
+
+
+ + +
+
+ +
+
+
+ +
+
+
+ +
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + diff --git a/demos/vanilla/nocookies/identify.html.tpl b/demos/vanilla/nocookies/identify.html.tpl new file mode 100644 index 0000000..b278a1e --- /dev/null +++ b/demos/vanilla/nocookies/identify.html.tpl @@ -0,0 +1,138 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: identify API

+

+ Simple script tag integration showing how to send a hashed Email address and optional publisher + user ID to your sandbox. +

+
+
+ +
+
+
+
+ + +
+
+
+ + +
+
+ +
+
+
+ +
+
+
+ +
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + diff --git a/demos/vanilla/nocookies/profile.html b/demos/vanilla/nocookies/profile.html new file mode 100644 index 0000000..2f528b9 --- /dev/null +++ b/demos/vanilla/nocookies/profile.html @@ -0,0 +1,120 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: profile API

+

Shows how to set visitor traits (e.g., age=45) and sync them to your sandbox.

+
+          
+            // Set some traits on the current visitor:
+            optable.instance.profile({ gender: "F", age: 38, favColor: "blue" });
+
+            // Set some new traits and update some existing on the current visitor:
+            optable.instance.profile({ favColor: "green", firstName: "Mary", lastName: "Smith" });
+          
+          
+
+
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + diff --git a/demos/vanilla/nocookies/profile.html.tpl b/demos/vanilla/nocookies/profile.html.tpl new file mode 100644 index 0000000..46c51be --- /dev/null +++ b/demos/vanilla/nocookies/profile.html.tpl @@ -0,0 +1,120 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: profile API

+

Shows how to set visitor traits (e.g., age=45) and sync them to your sandbox.

+
+          
+            // Set some traits on the current visitor:
+            optable.instance.profile({ gender: "F", age: 38, favColor: "blue" });
+
+            // Set some new traits and update some existing on the current visitor:
+            optable.instance.profile({ favColor: "green", firstName: "Mary", lastName: "Smith" });
+          
+          
+
+
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + diff --git a/demos/vanilla/nocookies/targeting/gam360-cached.html b/demos/vanilla/nocookies/targeting/gam360-cached.html new file mode 100644 index 0000000..61c62f5 --- /dev/null +++ b/demos/vanilla/nocookies/targeting/gam360-cached.html @@ -0,0 +1,171 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: cached targeting & GAM360 activation

+

+ Shows how to load and cache active cohorts in a visitor's browser. Separately, cached cohorts are passed to + Google Ad Manager (GAM) via the + Google Publisher Tag (GPT) for + ad targeting. +

+

+ In this example, we use the targetingFromCache() API to retrieve any targeting data from + browser LocalStorage, in order to pass it to GPT via googletag.pubads().setTargeting(). We also + call the SDK targeting API which will fetch the latest targeting data from our sandbox and + cache it locally for later use. Since these two events happen asynchronously, it's possible that the + targeting data passed to GAM is slightly outdated. To ensure ad targeting accuracy, we recommend calling + targeting to update the local cache on every page load. +

+

+ If you are comfortable with disabling initial load on GAM ads and always loading them explicitly with the + very latest targeting data, have a look at the + original targeting & GAM360 activation example instead. +

+
+
+ +
+
+
web-sdk-demo-gam360/header-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/box-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/footer-ad
+ +
+
+
+
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + + + diff --git a/demos/vanilla/nocookies/targeting/gam360-cached.html.tpl b/demos/vanilla/nocookies/targeting/gam360-cached.html.tpl new file mode 100644 index 0000000..708fe02 --- /dev/null +++ b/demos/vanilla/nocookies/targeting/gam360-cached.html.tpl @@ -0,0 +1,171 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: cached targeting & GAM360 activation

+

+ Shows how to load and cache active cohorts in a visitor's browser. Separately, cached cohorts are passed to + Google Ad Manager (GAM) via the + Google Publisher Tag (GPT) for + ad targeting. +

+

+ In this example, we use the targetingFromCache() API to retrieve any targeting data from + browser LocalStorage, in order to pass it to GPT via googletag.pubads().setTargeting(). We also + call the SDK targeting API which will fetch the latest targeting data from our sandbox and + cache it locally for later use. Since these two events happen asynchronously, it's possible that the + targeting data passed to GAM is slightly outdated. To ensure ad targeting accuracy, we recommend calling + targeting to update the local cache on every page load. +

+

+ If you are comfortable with disabling initial load on GAM ads and always loading them explicitly with the + very latest targeting data, have a look at the + original targeting & GAM360 activation example instead. +

+
+
+ +
+
+
web-sdk-demo-gam360/header-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/box-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/footer-ad
+ +
+
+
+
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + + + diff --git a/demos/vanilla/nocookies/targeting/gam360.html b/demos/vanilla/nocookies/targeting/gam360.html new file mode 100644 index 0000000..da3e32e --- /dev/null +++ b/demos/vanilla/nocookies/targeting/gam360.html @@ -0,0 +1,178 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: targeting & GAM360 activation

+

+ Shows how to load active cohorts for a visitor and pass them to + Google Ad Manager (GAM) via the + Google Publisher Tag (GPT) for + ad targeting. +

+

+ In this example, the call to the targeting API happens first and, on success or error, banner + ads are loaded from Optable's demo GAM account via googletag.pubads().refresh(). In order to + prevent ads loading until the asynchronous targeting call is done, we start by disabling + automatic ads loading with googletag.pubads().disableInitialLoad(). +

+

+ To see an alternate way of loading GAM ads with targeting data where disableInitialLoad() is + not required, check out the + cached targeting & GAM360 activation example + instead. +

+
+
+ +
+
+
web-sdk-demo-gam360/header-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/box-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/footer-ad
+ +
+
+
+
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + + + diff --git a/demos/vanilla/nocookies/targeting/gam360.html.tpl b/demos/vanilla/nocookies/targeting/gam360.html.tpl new file mode 100644 index 0000000..3caf3f0 --- /dev/null +++ b/demos/vanilla/nocookies/targeting/gam360.html.tpl @@ -0,0 +1,178 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: targeting & GAM360 activation

+

+ Shows how to load active cohorts for a visitor and pass them to + Google Ad Manager (GAM) via the + Google Publisher Tag (GPT) for + ad targeting. +

+

+ In this example, the call to the targeting API happens first and, on success or error, banner + ads are loaded from Optable's demo GAM account via googletag.pubads().refresh(). In order to + prevent ads loading until the asynchronous targeting call is done, we start by disabling + automatic ads loading with googletag.pubads().disableInitialLoad(). +

+

+ To see an alternate way of loading GAM ads with targeting data where disableInitialLoad() is + not required, check out the + cached targeting & GAM360 activation example + instead. +

+
+
+ +
+
+
web-sdk-demo-gam360/header-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/box-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/footer-ad
+ +
+
+
+
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + + + diff --git a/demos/vanilla/nocookies/targeting/prebid-us-east-16.html b/demos/vanilla/nocookies/targeting/prebid-us-east-16.html new file mode 100644 index 0000000..753936a --- /dev/null +++ b/demos/vanilla/nocookies/targeting/prebid-us-east-16.html @@ -0,0 +1,304 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: targeting & Prebid.js activation

+

+ Shows how to load active cohorts for a visitor and pass them to Prebid.js via + setConfig-fpd. + It's assumed in this example that your primary ad server is + Google Ad Manager (GAM) and that you are integrated with it + using the + Google Publisher Tag (GPT), so + we also pass matching active cohorts to GAM. +

+

+ In this example, we use the targetingFromCache API to retrieve any targeting data from browser + LocalStorage, in order to pass it to both Prebid.js and GPT. We also call the SDK targeting API + which will fetch the latest targeting data from our sandbox and cache it locally for later use. Since these + two events happen asynchronously, it's possible that the targeting data passed to GAM is slightly outdated. + To ensure ad targeting accuracy, we recommend calling targeting to update the local cache on + every page load. +

+
+
+ +
+
+
web-sdk-demo-gam360/header-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/box-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/footer-ad
+ +
+
+
+
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + + + diff --git a/demos/vanilla/nocookies/targeting/prebid-us-east-16.html.tpl b/demos/vanilla/nocookies/targeting/prebid-us-east-16.html.tpl new file mode 100644 index 0000000..9cf2f5e --- /dev/null +++ b/demos/vanilla/nocookies/targeting/prebid-us-east-16.html.tpl @@ -0,0 +1,304 @@ + + + + + Optable Web SDK Demos + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+

Example: targeting & Prebid.js activation

+

+ Shows how to load active cohorts for a visitor and pass them to Prebid.js via + setConfig-fpd. + It's assumed in this example that your primary ad server is + Google Ad Manager (GAM) and that you are integrated with it + using the + Google Publisher Tag (GPT), so + we also pass matching active cohorts to GAM. +

+

+ In this example, we use the targetingFromCache API to retrieve any targeting data from browser + LocalStorage, in order to pass it to both Prebid.js and GPT. We also call the SDK targeting API + which will fetch the latest targeting data from our sandbox and cache it locally for later use. Since these + two events happen asynchronously, it's possible that the targeting data passed to GAM is slightly outdated. + To ensure ad targeting accuracy, we recommend calling targeting to update the local cache on + every page load. +

+
+
+ +
+
+
web-sdk-demo-gam360/header-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/box-ad
+ +
+
+
+
+
+
web-sdk-demo-gam360/footer-ad
+ +
+
+
+
+
+
+ Home | Contact | + Privacy | + LinkedIn | + Twitter +
+
+
+
+ + + + + + diff --git a/demos/vanilla/nocookies/targeting/prebid-us-east-16.js b/demos/vanilla/nocookies/targeting/prebid-us-east-16.js new file mode 100644 index 0000000..c8a6847 --- /dev/null +++ b/demos/vanilla/nocookies/targeting/prebid-us-east-16.js @@ -0,0 +1,5 @@ +/* prebid.js v4.18.0-pre +Updated : 2020-11-26 */ +!function(u){var s=window.pbjsChunk;window.pbjsChunk=function(e,t,n){for(var r,i,o,a=0,c=[];a>t/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e)},t.getBidIdParameter=function(e,t){if(t&&t[e])return t[e];return""},t.tryAppendQueryString=function(e,t,n){if(n)return e+t+"="+encodeURIComponent(n)+"&";return e},t.parseQueryStringParameters=function(e){var t="";for(var n in e)e.hasOwnProperty(n)&&(t+=n+"="+encodeURIComponent(e[n])+"&");return t=t.replace(/&$/,"")},t.transformAdServerTargetingObj=function(t){return t&&0';return n+=''},t.createTrackPixelIframeHtml=se,t.getValueString=de,t.uniques=fe,t.flatten=le,t.getBidRequest=function(n,e){return n?(e.some(function(e){var t=c()(e.bids,function(t){return["bidId","adId","bid_id"].some(function(e){return t[e]===n})});return t&&(r=t),t}),r):void 0;var r},t.getKeys=pe,t.getValue=ge,t.getKeyByValue=function(e,t){for(var n in e)if(e.hasOwnProperty(n)&&e[n]===t)return n},t.getBidderCodes=function(){return(0t[n]?-1:0}},t.parseQS=Ie,t.formatQS=Ce,t.parseUrl=function(e,t){var n=document.createElement("a");t&&"noDecodeWholeURL"in t&&t.noDecodeWholeURL?n.href=e:n.href=decodeURIComponent(e);var r=t&&"decodeSearchAsString"in t&&t.decodeSearchAsString;return{href:n.href,protocol:(n.protocol||"").replace(/:$/,""),hostname:n.hostname,port:+n.port,pathname:n.pathname.replace(/^(?!\/)/,"/"),search:r?n.search:k.parseQS(n.search||""),hash:(n.hash||"").replace(/^#/,""),host:n.host||window.location.host}},t.buildUrl=function(e){return(e.protocol||"http")+"://"+(e.host||e.hostname+(e.port?":".concat(e.port):""))+(e.pathname||"")+(e.search?"?".concat(k.formatQS(e.search||"")):"")+(e.hash?"#".concat(e.hash):"")},t.deepEqual=je,t.mergeDeep=we,t.cyrb53Hash=function(e){for(var t,n=1>>16,2246822507)^r(o^o>>>13,3266489909),(4294967296*(2097151&(o=r(o^o>>>16,2246822507)^r(i^i>>>13,3266489909)))+(i>>>0)).toString()};var r=n(3),i=n(159),o=n.n(i),a=n(10),c=n.n(a),u=n(12),s=n.n(u),d=n(160);n.d(t,"deepAccess",function(){return d.a});var f=n(161);function l(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(e)))return;var n=[],r=!0,i=!1,o=void 0;try{for(var a,c=e[Symbol.iterator]();!(r=(a=c.next()).done)&&(n.push(a.value),!t||n.length!==t);r=!0);}catch(e){i=!0,o=e}finally{try{r||null==c.return||c.return()}finally{if(i)throw o}}return n}(e,t)||g(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(e){return function(e){if(Array.isArray(e))return b(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||g(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function g(e,t){if(e){if("string"==typeof e)return b(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?b(e,t):void 0}}function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n