@mparticle/web-sdk 3.1.0 → 3.2.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.md CHANGED
@@ -153,10 +153,12 @@ workflows in order:
153
153
  bootstrap permits all kit tags to be absent so the first synchronized release
154
154
  can establish them. After building the target version, Step 1 also packs and
155
155
  registry-preflights all kit artifacts before publishing core. It then checks
156
- out the immutable release tag, publishes all
157
- packages in `kits/publish-matrix.json` sequentially, and verifies that the
158
- core SDK and every kit have the expected version, artifact integrity, and
159
- npm dist-tag. A rerun skips an existing kit only when its artifact is
156
+ out the immutable release tag, waits up to five minutes for core to become
157
+ visible on npm, and publishes all packages in `kits/publish-matrix.json`
158
+ sequentially. After all publishes finish, one final audit waits up to five
159
+ minutes for npm propagation and verifies that
160
+ the core SDK and every kit have the expected version, artifact integrity,
161
+ and npm dist-tag. A rerun skips an existing kit only when its artifact is
160
162
  identical. `dryRun=true` previews the merge and semantic-release result
161
163
  without creating a branch or publishing; `dryRun=false` creates/pushes the
162
164
  release branch and publishes. If core publishes but kit publication cannot
@@ -15,7 +15,7 @@ map:function map(a,b){var c,d,e;if(null===this)throw new TypeError(" this is nul
15
15
  filter:function filter(a/*, thisArg*/){if(void 0===this||null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if("function"!=typeof a)throw new TypeError;for(var d=[],e=2<=arguments.length?arguments[1]:void 0,f=0;f<c;f++)if(f in b){var g=b[f];a.call(e,g,f,b)&&d.push(g);}return d},// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
16
16
  isArray:function isArray(a){return "[object Array]"===Object.prototype.toString.call(a)},Base64:Base64$1};
17
17
 
18
- var version = "3.1.0";
18
+ var version = "3.2.1";
19
19
 
20
20
  var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodHasBeenDeprecated:"has been deprecated.",MethodMarkedForDeprecationPostfix:"is a deprecated method and will be removed in future releases.",AlternativeMethodPrefix:"Please use the alternate method:"},ErrorMessages:{NoToken:"A token must be specified.",EventNameInvalidType:"Event name must be a valid string value.",EventDataInvalidType:"Event data must be a valid object hash.",LoggingDisabled:"Event logging is currently disabled.",CookieParseError:"Could not parse cookie",EventEmpty:"Event object is null or undefined, cancelling send",APIRequestEmpty:"APIRequest is null or undefined, cancelling send",NoEventType:"Event type must be specified.",TransactionIdRequired:"Transaction ID is required",TransactionRequired:"A transaction attributes object is required",PromotionIdRequired:"Promotion ID is required",BadAttribute:"Attribute value cannot be object or array",BadKey:"Key value cannot be object or array",BadLogPurchase:"Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions",AudienceAPINotEnabled:"Your workspace is not enabled to retrieve user audiences."},InformationMessages:{CookieSearch:"Searching for cookie",CookieFound:"Cookie found, parsing values",CookieNotFound:"Cookies not found",CookieSet:"Setting cookie",CookieSync:"Performing cookie sync",SendBegin:"Starting to send event",SendIdentityBegin:"Starting to send event to identity server",SendWindowsPhone:"Sending event to Windows Phone container",SendIOS:"Calling iOS path: ",SendAndroid:"Calling Android JS interface method: ",SendHttp:"Sending event to mParticle HTTP service",SendAliasHttp:"Sending alias request to mParticle HTTP service",SendIdentityHttp:"Sending event to mParticle HTTP service",StartingNewSession:"Starting new Session",StartingLogEvent:"Starting to log event",StartingLogOptOut:"Starting to log user opt in/out",StartingEndSession:"Starting to end session",StartingInitialization:"Starting to initialize",StartingLogCommerceEvent:"Starting to log commerce event",StartingAliasRequest:"Starting to Alias MPIDs",LoadingConfig:"Loading configuration options",AbandonLogEvent:"Cannot log event, logging disabled or developer token not set",AbandonAliasUsers:"Cannot Alias Users, logging disabled or developer token not set",AbandonStartSession:"Cannot start session, logging disabled or developer token not set",AbandonEndSession:"Cannot end session, logging disabled or developer token not set",NoSessionToEnd:"Cannot end session, no active session found"},ValidationMessages:{ModifyIdentityRequestUserIdentitiesPresent:"identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again",IdentityRequesetInvalidKey:"There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.",OnUserAliasType:"The onUserAlias value must be a function.",UserIdentities:"The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidKey:"There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidValues:"All user identity values must be strings or null. Request not sent to server. Please fix and try again.",AliasMissingMpid:"Alias Request must contain both a destinationMpid and a sourceMpid",AliasNonUniqueMpid:"Alias Request's destinationMpid and sourceMpid must be unique",AliasMissingTime:"Alias Request must have both a startTime and an endTime",AliasStartBeforeEndTime:"Alias Request's endTime must be later than its startTime"}},NativeSdkPaths:{LogEvent:"logEvent",SetUserTag:"setUserTag",RemoveUserTag:"removeUserTag",SetUserAttribute:"setUserAttribute",RemoveUserAttribute:"removeUserAttribute",SetSessionAttribute:"setSessionAttribute",LogOut:"logOut",SetUserAttributeList:"setUserAttributeList",RemoveAllUserAttributes:"removeAllUserAttributes",GetUserAttributesLists:"getUserAttributesLists",GetAllUserAttributes:"getAllUserAttributes",Identify:"identify",Logout:"logout",Login:"login",Modify:"modify",Alias:"aliasUsers",Upload:"upload"},StorageNames:{localStorageName:"mprtcl-api",localStorageNameV3:"mprtcl-v3",cookieName:"mprtcl-api",cookieNameV2:"mprtcl-v2",cookieNameV3:"mprtcl-v3",localStorageNameV4:"mprtcl-v4",cookieNameV4:"mprtcl-v4",currentStorageName:"mprtcl-v4"},DefaultConfig:{cookieDomain:null,cookieExpiration:365,logLevel:null,timeout:300,sessionTimeout:30,forwarderStatsTimeout:5e3,integrationDelayTimeout:5e3,maxCookieSize:3e3,aliasMaxWindow:90,uploadInterval:0// Maximum milliseconds in between batch uploads, below 500 will mean immediate upload. The server returns this as a string, but we are using it as a number internally
21
21
  },DefaultBaseUrls:{v1SecureServiceUrl:"jssdks.mparticle.com/v1/JS/",v2SecureServiceUrl:"jssdks.mparticle.com/v2/JS/",v3SecureServiceUrl:"jssdks.mparticle.com/v3/JS/",configUrl:"jssdkcdns.mparticle.com/JS/v2/",identityUrl:"identity.mparticle.com/v1/",aliasUrl:"jssdks.mparticle.com/v1/identity/",userAudienceUrl:"nativesdks.mparticle.com/v1/"},// These are the paths that are used to construct the CNAME urls
@@ -148,7 +148,10 @@ var Messages$a=Constants.Messages,createCookieString=function(a){return replaceC
148
148
  "".concat(1e7,"-").concat(1e3,"-").concat(4e3,"-").concat(8e3,"-").concat(1e11).replace(/[018]/g,// zeroes, ones, and eights with
149
149
  generateUniqueId// random hex digits
150
150
  )},getRampNumber=function(a){if(!a)return 100;var b=generateHash(a);return Math.abs(b%100)+1},isObject=function(a){var b=Object.prototype.toString.call(a);return "[object Object]"===b||"[object Error]"===b},parseNumber=function(a){if(isNaN(a)||!isFinite(a))return 0;var b=parseFloat(a);return isNaN(b)?0:b},parseSettingsString=function(a){try{return a?JSON.parse(a.replace(/&quot;/g,"\"")):[]}catch(a){throw new Error("Settings string contains invalid JSON")}},parseStringOrNumber=function(a){return isStringOrNumber(a)?a:null},replaceCommasWithPipes=function(a){return a.replace(/,/g,"|")},replacePipesWithCommas=function(a){return a.replace(/\|/g,",")},replaceApostrophesWithQuotes=function(a){return a.replace(/\'/g,"\"")},replaceQuotesWithApostrophes=function(a){return a.replace(/\"/g,"'")},replaceMPID=function(a,b){return a.replace("%%mpid%%",b)},replaceAmpWithAmpersand=function(a){return a.replace(/&amp;/g,"&")},createCookieSyncUrl=function(a,b,c,d,e){var f=replaceAmpWithAmpersand(b),g=c?replaceAmpWithAmpersand(c):null,h=replaceMPID(f,a),i=g?replaceMPID(g,a):"",j=h+encodeURIComponent(i);if(d){var k=j.includes("?")?"&":"?";j+="".concat(k,"domain=").concat(d);}if(e){var k=j.includes("?")?"&":"?";j+="".concat(k,"google_hm=").concat(e);}return j},WEB_SAFE_BASE64_REPLACEMENTS={"+":"-","/":"_","=":""},toWebSafeBase64=function(a){return btoa(a).replace(/[+/=]/g,function(a){return WEB_SAFE_BASE64_REPLACEMENTS[a]})},returnConvertedBoolean=function(a){return "false"!==a&&"0"!==a&&!!a},decoded=function(a){return decodeURIComponent(a.replace(/\+/g," "))},converted=function(a){return 0===a.indexOf("\"")&&(a=a.slice(1,-1).replace(/\\"/g,"\"").replace(/\\\\/g,"\\")),a},isString=function(a){return "string"==typeof a},isNumber=function(a){return "number"==typeof a},isBoolean=function(a){return "boolean"==typeof a},isFunction=function(a){return "function"==typeof a},isValidAttributeValue=function(a){return a!==void 0&&!isObject(a)&&!Array.isArray(a)},isValidCustomFlagProperty=function(a){return isNumber(a)||isString(a)||isBoolean(a)},toDataPlanSlug=function(a){// Make sure we are only acting on strings or numbers
151
- return isStringOrNumber(a)?a.toString().toLowerCase().replace(/[^0-9a-zA-Z]+/g,"_"):""},isDataPlanSlug=function(a){return a===toDataPlanSlug(a)},isStringOrNumber=function(a){return isString(a)||isNumber(a)},isEmpty=function(a){return null==a||!(Object.keys(a)||a).length},moveElementToEnd=function(a,b){return a.slice(0,b).concat(a.slice(b+1),a[b])},queryStringParser=function(a,b){void 0===b&&(b=[]);var c,d={},e={};if(!a)return d;if("undefined"!=typeof URL&&"undefined"!=typeof URLSearchParams){var f=new URL(a);c=new URLSearchParams(f.search);}else c=queryStringParserFallback(a);return (c.forEach(function(a,b){e[b.toLowerCase()]=a;}),isEmpty(b))?e:(b.forEach(function(a){var b=e[a.toLowerCase()];b&&(d[a]=b);}),d)},queryStringParserFallback=function(a){var b={},c=a.split("?")[1]||"",d=c.split("&");return d.forEach(function(a){var c=a.split("="),d=c[0],e=c.slice(1),f=e.join("=");if(d&&void 0!==f)try{b[d]=decodeURIComponent(f||"");}catch(a){console.error("Failed to decode value for key ".concat(d,": ").concat(a));}}),{get:function get(a){return b[a]},forEach:function forEach(a){for(var c in b)b.hasOwnProperty(c)&&a(b[c],c);}}},getCookies=function(a){// Helper function to parse cookies from document.cookie
151
+ return isStringOrNumber(a)?a.toString().toLowerCase().replace(/[^0-9a-zA-Z]+/g,"_"):""},isDataPlanSlug=function(a){return a===toDataPlanSlug(a)},isStringOrNumber=function(a){return isString(a)||isNumber(a)},isEmpty=function(a){return null==a||!(Object.keys(a)||a).length},moveElementToEnd=function(a,b){return a.slice(0,b).concat(a.slice(b+1),a[b])},hasOwnProp=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)},queryStringParser=function(a,b){void 0===b&&(b=[]);var c,d={},e={};if(!a)return d;if("undefined"!=typeof URL&&"undefined"!=typeof URLSearchParams){var f=new URL(a);c=new URLSearchParams(f.search);}else c=queryStringParserFallback(a);return (c.forEach(function(a,b){e[b.toLowerCase()]=a;}),isEmpty(b))?e:(b.forEach(function(a){var b=a.toLowerCase();// Callers pass their own key list, so `name` may not be from this URL.
152
+ hasOwnProp(e,b)&&e[b]&&(d[a]=e[b]);}),d)},queryStringParserFallback=function(a){var b={},c=a.split("?")[1]||"",d=c.split("&");return d.forEach(function(a){var c=a.split("="),d=c[0],e=c.slice(1),f=e.join("=");if(d&&void 0!==f)try{b[d]=decodeURIComponent(f||"");}catch(a){console.error("Failed to decode value for key ".concat(d,": ").concat(a));}}),{get:function get(a){return b[a]},forEach:function forEach(a){for(var c in b)// Keys come straight off the URL, so `?hasOwnProperty=1` would
153
+ // shadow the method and `params.hasOwnProperty(key)` would throw.
154
+ hasOwnProp(b,c)&&a(b[c],c);}}},getCookies=function(a){// Helper function to parse cookies from document.cookie
152
155
  var b=function parseCookies(){try{return "undefined"==typeof window?[]:window.document.cookie.split(";").map(function(a){return a.trim()})}catch(a){return console.error("Unable to parse cookies",a),[]}}();// Helper function to filter cookies by keys
153
156
  // Parse cookies from document.cookie
154
157
  // Filter cookies by keys if provided
@@ -166,6 +169,13 @@ return _typeof(a)},obfuscateDevData=function(a,b){return b?a:obfuscateData(a)};/
166
169
  // only used in store.js to sanitize server-side formatting of
167
170
  // booleans when checking for `isDevelopmentMode`
168
171
  // Should be removed in v3
172
+ // For keys that did not come from the object itself: `obj[name]` and `name in obj`
173
+ // both walk the prototype chain, so `constructor` is truthy on any plain object.
174
+ //
175
+ // Not `Object.hasOwn`, which Sonar recommends here (typescript:S6653). It is ES2022 and
176
+ // does not compile under this project's `lib: ["es5", "es6", "dom"]`; widening that
177
+ // would emit a call absent from every browser before 2021, and this same file still
178
+ // carries a fallback for browsers with no URLSearchParams.
169
179
  // Get cookies as a dictionary
170
180
  /**
171
181
  * Obfuscates an object by replacing all primitive values with their type names,
@@ -831,7 +841,13 @@ var allowedQueryParams=function(a){return queryStringParser(a,ALLOWED_QUERY_PARA
831
841
  // rather than a sort: it is deterministic without needing a comparator, and it
832
842
  // does not depend on the object's insertion order, so reordering the query string
833
843
  // cannot produce a different key.
834
- var capturedNames=function(a){return ALLOWED_QUERY_PARAMS.filter(function(b){return b in a})};// The dedup key: pathname plus the allowlisted params in a fixed order, so that
844
+ //
845
+ // Membership is an own-property check, not `in`. `in` walks the prototype
846
+ // chain, so a name matching an Object.prototype member reports as present on
847
+ // any plain object. ALLOWED_QUERY_PARAMS contains no such name, which was the
848
+ // only thing making `in` safe here — and it stops being a safe assumption the
849
+ // moment this list can be extended from configuration.
850
+ var capturedNames=function(a){return ALLOWED_QUERY_PARAMS.filter(function(b){return hasOwnProp(a,b)})};// The dedup key: pathname plus the allowlisted params in a fixed order, so that
835
851
  // reordering the query string is not a new page. Params outside the allowlist
836
852
  // never make it into `page.params` and so cannot key a view — nor can the hash.
837
853
  //
@@ -15,7 +15,7 @@ map:function map(a,b){var c,d,e;if(null===this)throw new TypeError(" this is nul
15
15
  filter:function filter(a/*, thisArg*/){if(void 0===this||null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if("function"!=typeof a)throw new TypeError;for(var d=[],e=2<=arguments.length?arguments[1]:void 0,f=0;f<c;f++)if(f in b){var g=b[f];a.call(e,g,f,b)&&d.push(g);}return d},// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
16
16
  isArray:function isArray(a){return "[object Array]"===Object.prototype.toString.call(a)},Base64:Base64$1};
17
17
 
18
- var version = "3.1.0";
18
+ var version = "3.2.1";
19
19
 
20
20
  var Constants={sdkVersion:version,sdkVendor:"mparticle",platform:"web",Messages:{DeprecationMessages:{MethodHasBeenDeprecated:"has been deprecated.",MethodMarkedForDeprecationPostfix:"is a deprecated method and will be removed in future releases.",AlternativeMethodPrefix:"Please use the alternate method:"},ErrorMessages:{NoToken:"A token must be specified.",EventNameInvalidType:"Event name must be a valid string value.",EventDataInvalidType:"Event data must be a valid object hash.",LoggingDisabled:"Event logging is currently disabled.",CookieParseError:"Could not parse cookie",EventEmpty:"Event object is null or undefined, cancelling send",APIRequestEmpty:"APIRequest is null or undefined, cancelling send",NoEventType:"Event type must be specified.",TransactionIdRequired:"Transaction ID is required",TransactionRequired:"A transaction attributes object is required",PromotionIdRequired:"Promotion ID is required",BadAttribute:"Attribute value cannot be object or array",BadKey:"Key value cannot be object or array",BadLogPurchase:"Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions",AudienceAPINotEnabled:"Your workspace is not enabled to retrieve user audiences."},InformationMessages:{CookieSearch:"Searching for cookie",CookieFound:"Cookie found, parsing values",CookieNotFound:"Cookies not found",CookieSet:"Setting cookie",CookieSync:"Performing cookie sync",SendBegin:"Starting to send event",SendIdentityBegin:"Starting to send event to identity server",SendWindowsPhone:"Sending event to Windows Phone container",SendIOS:"Calling iOS path: ",SendAndroid:"Calling Android JS interface method: ",SendHttp:"Sending event to mParticle HTTP service",SendAliasHttp:"Sending alias request to mParticle HTTP service",SendIdentityHttp:"Sending event to mParticle HTTP service",StartingNewSession:"Starting new Session",StartingLogEvent:"Starting to log event",StartingLogOptOut:"Starting to log user opt in/out",StartingEndSession:"Starting to end session",StartingInitialization:"Starting to initialize",StartingLogCommerceEvent:"Starting to log commerce event",StartingAliasRequest:"Starting to Alias MPIDs",LoadingConfig:"Loading configuration options",AbandonLogEvent:"Cannot log event, logging disabled or developer token not set",AbandonAliasUsers:"Cannot Alias Users, logging disabled or developer token not set",AbandonStartSession:"Cannot start session, logging disabled or developer token not set",AbandonEndSession:"Cannot end session, logging disabled or developer token not set",NoSessionToEnd:"Cannot end session, no active session found"},ValidationMessages:{ModifyIdentityRequestUserIdentitiesPresent:"identityRequests to modify require userIdentities to be present. Request not sent to server. Please fix and try again",IdentityRequesetInvalidKey:"There is an invalid key on your identityRequest object. It can only contain a `userIdentities` object and a `onUserAlias` function. Request not sent to server. Please fix and try again.",OnUserAliasType:"The onUserAlias value must be a function.",UserIdentities:"The userIdentities key must be an object with keys of identityTypes and values of strings. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidKey:"There is an invalid identity key on your `userIdentities` object within the identityRequest. Request not sent to server. Please fix and try again.",UserIdentitiesInvalidValues:"All user identity values must be strings or null. Request not sent to server. Please fix and try again.",AliasMissingMpid:"Alias Request must contain both a destinationMpid and a sourceMpid",AliasNonUniqueMpid:"Alias Request's destinationMpid and sourceMpid must be unique",AliasMissingTime:"Alias Request must have both a startTime and an endTime",AliasStartBeforeEndTime:"Alias Request's endTime must be later than its startTime"}},NativeSdkPaths:{LogEvent:"logEvent",SetUserTag:"setUserTag",RemoveUserTag:"removeUserTag",SetUserAttribute:"setUserAttribute",RemoveUserAttribute:"removeUserAttribute",SetSessionAttribute:"setSessionAttribute",LogOut:"logOut",SetUserAttributeList:"setUserAttributeList",RemoveAllUserAttributes:"removeAllUserAttributes",GetUserAttributesLists:"getUserAttributesLists",GetAllUserAttributes:"getAllUserAttributes",Identify:"identify",Logout:"logout",Login:"login",Modify:"modify",Alias:"aliasUsers",Upload:"upload"},StorageNames:{localStorageName:"mprtcl-api",localStorageNameV3:"mprtcl-v3",cookieName:"mprtcl-api",cookieNameV2:"mprtcl-v2",cookieNameV3:"mprtcl-v3",localStorageNameV4:"mprtcl-v4",cookieNameV4:"mprtcl-v4",currentStorageName:"mprtcl-v4"},DefaultConfig:{cookieDomain:null,cookieExpiration:365,logLevel:null,timeout:300,sessionTimeout:30,forwarderStatsTimeout:5e3,integrationDelayTimeout:5e3,maxCookieSize:3e3,aliasMaxWindow:90,uploadInterval:0// Maximum milliseconds in between batch uploads, below 500 will mean immediate upload. The server returns this as a string, but we are using it as a number internally
21
21
  },DefaultBaseUrls:{v1SecureServiceUrl:"jssdks.mparticle.com/v1/JS/",v2SecureServiceUrl:"jssdks.mparticle.com/v2/JS/",v3SecureServiceUrl:"jssdks.mparticle.com/v3/JS/",configUrl:"jssdkcdns.mparticle.com/JS/v2/",identityUrl:"identity.mparticle.com/v1/",aliasUrl:"jssdks.mparticle.com/v1/identity/",userAudienceUrl:"nativesdks.mparticle.com/v1/"},// These are the paths that are used to construct the CNAME urls
@@ -148,7 +148,10 @@ var Messages$a=Constants.Messages,createCookieString=function(a){return replaceC
148
148
  "".concat(1e7,"-").concat(1e3,"-").concat(4e3,"-").concat(8e3,"-").concat(1e11).replace(/[018]/g,// zeroes, ones, and eights with
149
149
  generateUniqueId// random hex digits
150
150
  )},getRampNumber=function(a){if(!a)return 100;var b=generateHash(a);return Math.abs(b%100)+1},isObject=function(a){var b=Object.prototype.toString.call(a);return "[object Object]"===b||"[object Error]"===b},parseNumber=function(a){if(isNaN(a)||!isFinite(a))return 0;var b=parseFloat(a);return isNaN(b)?0:b},parseSettingsString=function(a){try{return a?JSON.parse(a.replace(/&quot;/g,"\"")):[]}catch(a){throw new Error("Settings string contains invalid JSON")}},parseStringOrNumber=function(a){return isStringOrNumber(a)?a:null},replaceCommasWithPipes=function(a){return a.replace(/,/g,"|")},replacePipesWithCommas=function(a){return a.replace(/\|/g,",")},replaceApostrophesWithQuotes=function(a){return a.replace(/\'/g,"\"")},replaceQuotesWithApostrophes=function(a){return a.replace(/\"/g,"'")},replaceMPID=function(a,b){return a.replace("%%mpid%%",b)},replaceAmpWithAmpersand=function(a){return a.replace(/&amp;/g,"&")},createCookieSyncUrl=function(a,b,c,d,e){var f=replaceAmpWithAmpersand(b),g=c?replaceAmpWithAmpersand(c):null,h=replaceMPID(f,a),i=g?replaceMPID(g,a):"",j=h+encodeURIComponent(i);if(d){var k=j.includes("?")?"&":"?";j+="".concat(k,"domain=").concat(d);}if(e){var k=j.includes("?")?"&":"?";j+="".concat(k,"google_hm=").concat(e);}return j},WEB_SAFE_BASE64_REPLACEMENTS={"+":"-","/":"_","=":""},toWebSafeBase64=function(a){return btoa(a).replace(/[+/=]/g,function(a){return WEB_SAFE_BASE64_REPLACEMENTS[a]})},returnConvertedBoolean=function(a){return "false"!==a&&"0"!==a&&!!a},decoded=function(a){return decodeURIComponent(a.replace(/\+/g," "))},converted=function(a){return 0===a.indexOf("\"")&&(a=a.slice(1,-1).replace(/\\"/g,"\"").replace(/\\\\/g,"\\")),a},isString=function(a){return "string"==typeof a},isNumber=function(a){return "number"==typeof a},isBoolean=function(a){return "boolean"==typeof a},isFunction=function(a){return "function"==typeof a},isValidAttributeValue=function(a){return a!==void 0&&!isObject(a)&&!Array.isArray(a)},isValidCustomFlagProperty=function(a){return isNumber(a)||isString(a)||isBoolean(a)},toDataPlanSlug=function(a){// Make sure we are only acting on strings or numbers
151
- return isStringOrNumber(a)?a.toString().toLowerCase().replace(/[^0-9a-zA-Z]+/g,"_"):""},isDataPlanSlug=function(a){return a===toDataPlanSlug(a)},isStringOrNumber=function(a){return isString(a)||isNumber(a)},isEmpty=function(a){return null==a||!(Object.keys(a)||a).length},moveElementToEnd=function(a,b){return a.slice(0,b).concat(a.slice(b+1),a[b])},queryStringParser=function(a,b){void 0===b&&(b=[]);var c,d={},e={};if(!a)return d;if("undefined"!=typeof URL&&"undefined"!=typeof URLSearchParams){var f=new URL(a);c=new URLSearchParams(f.search);}else c=queryStringParserFallback(a);return (c.forEach(function(a,b){e[b.toLowerCase()]=a;}),isEmpty(b))?e:(b.forEach(function(a){var b=e[a.toLowerCase()];b&&(d[a]=b);}),d)},queryStringParserFallback=function(a){var b={},c=a.split("?")[1]||"",d=c.split("&");return d.forEach(function(a){var c=a.split("="),d=c[0],e=c.slice(1),f=e.join("=");if(d&&void 0!==f)try{b[d]=decodeURIComponent(f||"");}catch(a){console.error("Failed to decode value for key ".concat(d,": ").concat(a));}}),{get:function get(a){return b[a]},forEach:function forEach(a){for(var c in b)b.hasOwnProperty(c)&&a(b[c],c);}}},getCookies=function(a){// Helper function to parse cookies from document.cookie
151
+ return isStringOrNumber(a)?a.toString().toLowerCase().replace(/[^0-9a-zA-Z]+/g,"_"):""},isDataPlanSlug=function(a){return a===toDataPlanSlug(a)},isStringOrNumber=function(a){return isString(a)||isNumber(a)},isEmpty=function(a){return null==a||!(Object.keys(a)||a).length},moveElementToEnd=function(a,b){return a.slice(0,b).concat(a.slice(b+1),a[b])},hasOwnProp=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)},queryStringParser=function(a,b){void 0===b&&(b=[]);var c,d={},e={};if(!a)return d;if("undefined"!=typeof URL&&"undefined"!=typeof URLSearchParams){var f=new URL(a);c=new URLSearchParams(f.search);}else c=queryStringParserFallback(a);return (c.forEach(function(a,b){e[b.toLowerCase()]=a;}),isEmpty(b))?e:(b.forEach(function(a){var b=a.toLowerCase();// Callers pass their own key list, so `name` may not be from this URL.
152
+ hasOwnProp(e,b)&&e[b]&&(d[a]=e[b]);}),d)},queryStringParserFallback=function(a){var b={},c=a.split("?")[1]||"",d=c.split("&");return d.forEach(function(a){var c=a.split("="),d=c[0],e=c.slice(1),f=e.join("=");if(d&&void 0!==f)try{b[d]=decodeURIComponent(f||"");}catch(a){console.error("Failed to decode value for key ".concat(d,": ").concat(a));}}),{get:function get(a){return b[a]},forEach:function forEach(a){for(var c in b)// Keys come straight off the URL, so `?hasOwnProperty=1` would
153
+ // shadow the method and `params.hasOwnProperty(key)` would throw.
154
+ hasOwnProp(b,c)&&a(b[c],c);}}},getCookies=function(a){// Helper function to parse cookies from document.cookie
152
155
  var b=function parseCookies(){try{return "undefined"==typeof window?[]:window.document.cookie.split(";").map(function(a){return a.trim()})}catch(a){return console.error("Unable to parse cookies",a),[]}}();// Helper function to filter cookies by keys
153
156
  // Parse cookies from document.cookie
154
157
  // Filter cookies by keys if provided
@@ -166,6 +169,13 @@ return _typeof(a)},obfuscateDevData=function(a,b){return b?a:obfuscateData(a)};/
166
169
  // only used in store.js to sanitize server-side formatting of
167
170
  // booleans when checking for `isDevelopmentMode`
168
171
  // Should be removed in v3
172
+ // For keys that did not come from the object itself: `obj[name]` and `name in obj`
173
+ // both walk the prototype chain, so `constructor` is truthy on any plain object.
174
+ //
175
+ // Not `Object.hasOwn`, which Sonar recommends here (typescript:S6653). It is ES2022 and
176
+ // does not compile under this project's `lib: ["es5", "es6", "dom"]`; widening that
177
+ // would emit a call absent from every browser before 2021, and this same file still
178
+ // carries a fallback for browsers with no URLSearchParams.
169
179
  // Get cookies as a dictionary
170
180
  /**
171
181
  * Obfuscates an object by replacing all primitive values with their type names,
@@ -831,7 +841,13 @@ var allowedQueryParams=function(a){return queryStringParser(a,ALLOWED_QUERY_PARA
831
841
  // rather than a sort: it is deterministic without needing a comparator, and it
832
842
  // does not depend on the object's insertion order, so reordering the query string
833
843
  // cannot produce a different key.
834
- var capturedNames=function(a){return ALLOWED_QUERY_PARAMS.filter(function(b){return b in a})};// The dedup key: pathname plus the allowlisted params in a fixed order, so that
844
+ //
845
+ // Membership is an own-property check, not `in`. `in` walks the prototype
846
+ // chain, so a name matching an Object.prototype member reports as present on
847
+ // any plain object. ALLOWED_QUERY_PARAMS contains no such name, which was the
848
+ // only thing making `in` safe here — and it stops being a safe assumption the
849
+ // moment this list can be extended from configuration.
850
+ var capturedNames=function(a){return ALLOWED_QUERY_PARAMS.filter(function(b){return hasOwnProp(a,b)})};// The dedup key: pathname plus the allowlisted params in a fixed order, so that
835
851
  // reordering the query string is not a new page. Params outside the allowlist
836
852
  // never make it into `page.params` and so cannot key a view — nor can the hash.
837
853
  //
package/dist/mparticle.js CHANGED
@@ -204,7 +204,7 @@ var mParticle = (function () {
204
204
  Base64: Base64$1
205
205
  };
206
206
 
207
- var version = "3.1.0";
207
+ var version = "3.2.1";
208
208
 
209
209
  var Constants = {
210
210
  sdkVersion: version,
@@ -763,6 +763,16 @@ var mParticle = (function () {
763
763
  var moveElementToEnd = function moveElementToEnd(array, index) {
764
764
  return array.slice(0, index).concat(array.slice(index + 1), array[index]);
765
765
  };
766
+ // For keys that did not come from the object itself: `obj[name]` and `name in obj`
767
+ // both walk the prototype chain, so `constructor` is truthy on any plain object.
768
+ //
769
+ // Not `Object.hasOwn`, which Sonar recommends here (typescript:S6653). It is ES2022 and
770
+ // does not compile under this project's `lib: ["es5", "es6", "dom"]`; widening that
771
+ // would emit a call absent from every browser before 2021, and this same file still
772
+ // carries a fallback for browsers with no URLSearchParams.
773
+ var hasOwnProp = function hasOwnProp(obj, key) {
774
+ return Object.prototype.hasOwnProperty.call(obj, key);
775
+ };
766
776
  var queryStringParser = function queryStringParser(url, keys) {
767
777
  if (keys === void 0) {
768
778
  keys = [];
@@ -784,9 +794,10 @@ var mParticle = (function () {
784
794
  return lowerCaseUrlParams;
785
795
  } else {
786
796
  keys.forEach(function (key) {
787
- var value = lowerCaseUrlParams[key.toLowerCase()];
788
- if (value) {
789
- results[key] = value;
797
+ var name = key.toLowerCase();
798
+ // Callers pass their own key list, so `name` may not be from this URL.
799
+ if (hasOwnProp(lowerCaseUrlParams, name) && lowerCaseUrlParams[name]) {
800
+ results[key] = lowerCaseUrlParams[name];
790
801
  }
791
802
  });
792
803
  }
@@ -815,7 +826,9 @@ var mParticle = (function () {
815
826
  },
816
827
  forEach: function forEach(callback) {
817
828
  for (var key in params) {
818
- if (params.hasOwnProperty(key)) {
829
+ // Keys come straight off the URL, so `?hasOwnProperty=1` would
830
+ // shadow the method and `params.hasOwnProperty(key)` would throw.
831
+ if (hasOwnProp(params, key)) {
819
832
  callback(params[key], key);
820
833
  }
821
834
  }
@@ -6411,9 +6424,15 @@ var mParticle = (function () {
6411
6424
  // rather than a sort: it is deterministic without needing a comparator, and it
6412
6425
  // does not depend on the object's insertion order, so reordering the query string
6413
6426
  // cannot produce a different key.
6427
+ //
6428
+ // Membership is an own-property check, not `in`. `in` walks the prototype
6429
+ // chain, so a name matching an Object.prototype member reports as present on
6430
+ // any plain object. ALLOWED_QUERY_PARAMS contains no such name, which was the
6431
+ // only thing making `in` safe here — and it stops being a safe assumption the
6432
+ // moment this list can be extended from configuration.
6414
6433
  var capturedNames = function capturedNames(params) {
6415
6434
  return ALLOWED_QUERY_PARAMS.filter(function (name) {
6416
- return name in params;
6435
+ return hasOwnProp(params, name);
6417
6436
  });
6418
6437
  };
6419
6438
  // The dedup key: pathname plus the allowlisted params in a fixed order, so that
@@ -43,6 +43,7 @@ declare const isStringOrNumber: (value: any) => boolean;
43
43
  declare const isEmpty: (value: Dictionary<any> | string | null | undefined) => boolean;
44
44
  declare const mergeObjects: <T extends object>(...objects: T[]) => T;
45
45
  declare const moveElementToEnd: <T>(array: T[], index: number) => T[];
46
+ declare const hasOwnProp: (obj: object, key: string) => boolean;
46
47
  declare const queryStringParser: (url: string, keys?: string[]) => Dictionary<string>;
47
48
  declare const getCookies: (keys?: string[]) => Dictionary<string>;
48
49
  declare const getHref: () => string;
@@ -82,4 +83,4 @@ declare const obfuscateData: (value: any) => any;
82
83
  declare const obfuscateDevData: (data: any, isDevelopmentMode?: boolean) => any;
83
84
  declare function extend(...args: any[]): any;
84
85
  declare const getErrorMessage: (e: unknown, fallback?: string) => string;
85
- export { createCookieString, revertCookieString, createCookieSyncUrl, toWebSafeBase64, valueof, AttributeValue, converted, decoded, obfuscateDevData, filterDictionaryWithHash, findKeyInObject, generateDeprecationMessage, generateHash, generateUniqueId, getErrorMessage, getRampNumber, inArray, isObject, isStringOrNumber, obfuscateData, parseConfig, parseNumber, parseSettingsString, parseStringOrNumber, replaceCommasWithPipes, replacePipesWithCommas, replaceApostrophesWithQuotes, replaceQuotesWithApostrophes, returnConvertedBoolean, toDataPlanSlug, isString, isNumber, isFunction, isDataPlanSlug, isEmpty, isValidAttributeValue, isValidCustomFlagProperty, mergeObjects, moveElementToEnd, queryStringParser, getCookies, getHref, replaceMPID, replaceAmpWithAmpersand, extend, };
86
+ export { createCookieString, revertCookieString, createCookieSyncUrl, toWebSafeBase64, valueof, AttributeValue, converted, decoded, obfuscateDevData, filterDictionaryWithHash, findKeyInObject, generateDeprecationMessage, generateHash, generateUniqueId, getErrorMessage, getRampNumber, inArray, isObject, isStringOrNumber, obfuscateData, parseConfig, parseNumber, parseSettingsString, parseStringOrNumber, replaceCommasWithPipes, replacePipesWithCommas, replaceApostrophesWithQuotes, replaceQuotesWithApostrophes, returnConvertedBoolean, toDataPlanSlug, isString, isNumber, isFunction, isDataPlanSlug, isEmpty, isValidAttributeValue, isValidCustomFlagProperty, mergeObjects, moveElementToEnd, queryStringParser, hasOwnProp, getCookies, getHref, replaceMPID, replaceAmpWithAmpersand, extend, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-sdk",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "mParticle core SDK for web applications",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -1,7 +1,7 @@
1
1
  import { IMParticleWebSDKInstance } from './mp-instance';
2
2
  import { BaseEvent } from './sdkRuntimeModels';
3
3
  import { EventType, MessageType } from './types';
4
- import { Dictionary, getHref, queryStringParser } from './utils';
4
+ import { Dictionary, getHref, hasOwnProp, queryStringParser } from './utils';
5
5
 
6
6
  type HistoryStateMethod = History['pushState'];
7
7
  type HistoryMethodName = 'pushState' | 'replaceState';
@@ -127,8 +127,14 @@ export const allowedQueryParams = (href: string): Dictionary<string> =>
127
127
  // rather than a sort: it is deterministic without needing a comparator, and it
128
128
  // does not depend on the object's insertion order, so reordering the query string
129
129
  // cannot produce a different key.
130
+ //
131
+ // Membership is an own-property check, not `in`. `in` walks the prototype
132
+ // chain, so a name matching an Object.prototype member reports as present on
133
+ // any plain object. ALLOWED_QUERY_PARAMS contains no such name, which was the
134
+ // only thing making `in` safe here — and it stops being a safe assumption the
135
+ // moment this list can be extended from configuration.
130
136
  const capturedNames = (params: Dictionary<string>): string[] =>
131
- ALLOWED_QUERY_PARAMS.filter(name => name in params);
137
+ ALLOWED_QUERY_PARAMS.filter(name => hasOwnProp(params, name));
132
138
 
133
139
  // The dedup key: pathname plus the allowlisted params in a fixed order, so that
134
140
  // reordering the query string is not a new page. Params outside the allowlist
package/src/utils.ts CHANGED
@@ -309,6 +309,16 @@ const mergeObjects = <T extends object>(...objects: T[]): T => {
309
309
  const moveElementToEnd = <T>(array: T[], index: number): T[] =>
310
310
  array.slice(0, index).concat(array.slice(index + 1), array[index]);
311
311
 
312
+ // For keys that did not come from the object itself: `obj[name]` and `name in obj`
313
+ // both walk the prototype chain, so `constructor` is truthy on any plain object.
314
+ //
315
+ // Not `Object.hasOwn`, which Sonar recommends here (typescript:S6653). It is ES2022 and
316
+ // does not compile under this project's `lib: ["es5", "es6", "dom"]`; widening that
317
+ // would emit a call absent from every browser before 2021, and this same file still
318
+ // carries a fallback for browsers with no URLSearchParams.
319
+ const hasOwnProp = (obj: object, key: string): boolean =>
320
+ Object.prototype.hasOwnProperty.call(obj, key);
321
+
312
322
  const queryStringParser = (
313
323
  url: string,
314
324
  keys: string[] = []
@@ -334,9 +344,11 @@ const queryStringParser = (
334
344
  return lowerCaseUrlParams;
335
345
  } else {
336
346
  keys.forEach(key => {
337
- const value = lowerCaseUrlParams[key.toLowerCase()];
338
- if (value) {
339
- results[key] = value;
347
+ const name = key.toLowerCase();
348
+
349
+ // Callers pass their own key list, so `name` may not be from this URL.
350
+ if (hasOwnProp(lowerCaseUrlParams, name) && lowerCaseUrlParams[name]) {
351
+ results[key] = lowerCaseUrlParams[name];
340
352
  }
341
353
  });
342
354
  }
@@ -372,7 +384,9 @@ const queryStringParserFallback = (url: string): URLSearchParamsFallback => {
372
384
  },
373
385
  forEach: function(callback: (value: string, key: string) => void) {
374
386
  for (var key in params) {
375
- if (params.hasOwnProperty(key)) {
387
+ // Keys come straight off the URL, so `?hasOwnProperty=1` would
388
+ // shadow the method and `params.hasOwnProperty(key)` would throw.
389
+ if (hasOwnProp(params, key)) {
376
390
  callback(params[key], key);
377
391
  }
378
392
  }
@@ -706,6 +720,7 @@ export {
706
720
  mergeObjects,
707
721
  moveElementToEnd,
708
722
  queryStringParser,
723
+ hasOwnProp,
709
724
  getCookies,
710
725
  getHref,
711
726
  replaceMPID,