From 1d8eab09f1dab19d72e9904e848c280869c3f24b Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Thu, 13 Nov 2025 11:42:53 +0700 Subject: [PATCH] Move properties inside UAItem class into shared prototype --- src/main/ua-parser.js | 366 +++++++++++++++++++++--------------------- 1 file changed, 182 insertions(+), 184 deletions(-) diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index ec31ab9..69dc14e 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -1191,189 +1191,6 @@ } function UAItem (itemType, ua, rgxMap, uaCH) { - - this.get = function (prop) { - if (!prop) return this.data; - return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined; - }; - - this.set = function (prop, val) { - this.data[prop] = val; - return this; - }; - - this.setCH = function (ch) { - this.uaCH = ch; - return this; - }; - - this.detectFeature = function () { - if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) { - switch (this.itemType) { - case BROWSER: - // Brave-specific detection - if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) { - this.set(NAME, 'Brave'); - } - break; - case DEVICE: - // Chrome-specific detection: check for 'mobile' value of navigator.userAgentData - if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) { - this.set(TYPE, MOBILE); - } - // iPadOS-specific detection: identified as Mac, but has some iOS-only properties - if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) { - this.set(MODEL, 'iPad') - .set(TYPE, TABLET); - } - break; - case OS: - // Chrome-specific detection: check for 'platform' value of navigator.userAgentData - if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) { - this.set(NAME, NAVIGATOR_UADATA[PLATFORM]); - } - break; - case RESULT: - var data = this.data; - var detect = function (itemType) { - return data[itemType] - .getItem() - .detectFeature() - .get(); - }; - this.set(BROWSER, detect(BROWSER)) - .set(CPU, detect(CPU)) - .set(DEVICE, detect(DEVICE)) - .set(ENGINE, detect(ENGINE)) - .set(OS, detect(OS)); - } - } - return this; - }; - - this.parseUA = function () { - if (this.itemType != RESULT) { - rgxMapper.call(this.data, this.ua, this.rgxMap); - } - switch (this.itemType) { - case BROWSER: - this.set(MAJOR, majorize(this.get(VERSION))); - break; - case OS: - if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') { - // Based on the assumption that iOS version is tightly coupled with Safari version - var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version - if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) { - this.set(VERSION, realVersion[1]); // Set as iOS version - } - } - break; - } - return this; - }; - - this.parseCH = function () { - var uaCH = this.uaCH, - rgxMap = this.rgxMap; - - switch (this.itemType) { - case BROWSER: - case ENGINE: - var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName; - if (brands) { - for (var i=0; i= 13 ? '11' : '10'); - this.set(NAME, osName) - .set(VERSION, osVersion); - } - // Xbox-Specific Detection - if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') { - this.set(NAME, 'Xbox') - .set(VERSION, undefined); - } - break; - case RESULT: - var data = this.data; - var parse = function (itemType) { - return data[itemType] - .getItem() - .setCH(uaCH) - .parseCH() - .get(); - }; - this.set(BROWSER, parse(BROWSER)) - .set(CPU, parse(CPU)) - .set(DEVICE, parse(DEVICE)) - .set(ENGINE, parse(ENGINE)) - .set(OS, parse(OS)); - } - return this; - }; - setProps.call(this, [ ['itemType', itemType], ['ua', ua], @@ -1381,10 +1198,191 @@ ['rgxMap', rgxMap], ['data', createIData(this, itemType)] ]); - return this; } + UAItem.prototype.get = function (prop) { + if (!prop) return this.data; + return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined; + }; + + UAItem.prototype.set = function (prop, val) { + this.data[prop] = val; + return this; + }; + + UAItem.prototype.setCH = function (ch) { + this.uaCH = ch; + return this; + }; + + UAItem.prototype.detectFeature = function () { + if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) { + switch (this.itemType) { + case BROWSER: + // Brave-specific detection + if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) { + this.set(NAME, 'Brave'); + } + break; + case DEVICE: + // Chrome-specific detection: check for 'mobile' value of navigator.userAgentData + if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) { + this.set(TYPE, MOBILE); + } + // iPadOS-specific detection: identified as Mac, but has some iOS-only properties + if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) { + this.set(MODEL, 'iPad') + .set(TYPE, TABLET); + } + break; + case OS: + // Chrome-specific detection: check for 'platform' value of navigator.userAgentData + if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) { + this.set(NAME, NAVIGATOR_UADATA[PLATFORM]); + } + break; + case RESULT: + var data = this.data; + var detect = function (itemType) { + return data[itemType] + .getItem() + .detectFeature() + .get(); + }; + this.set(BROWSER, detect(BROWSER)) + .set(CPU, detect(CPU)) + .set(DEVICE, detect(DEVICE)) + .set(ENGINE, detect(ENGINE)) + .set(OS, detect(OS)); + } + } + return this; + }; + + UAItem.prototype.parseUA = function () { + if (this.itemType != RESULT) { + rgxMapper.call(this.data, this.ua, this.rgxMap); + } + switch (this.itemType) { + case BROWSER: + this.set(MAJOR, majorize(this.get(VERSION))); + break; + case OS: + if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') { + // Based on the assumption that iOS version is tightly coupled with Safari version + var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version + if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) { + this.set(VERSION, realVersion[1]); // Set as iOS version + } + } + break; + } + return this; + }; + + UAItem.prototype.parseCH = function () { + var uaCH = this.uaCH, + rgxMap = this.rgxMap; + + switch (this.itemType) { + case BROWSER: + case ENGINE: + var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName; + if (brands) { + for (var i=0; i= 13 ? '11' : '10'); + this.set(NAME, osName) + .set(VERSION, osVersion); + } + // Xbox-Specific Detection + if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') { + this.set(NAME, 'Xbox') + .set(VERSION, undefined); + } + break; + case RESULT: + var data = this.data; + var parse = function (itemType) { + return data[itemType] + .getItem() + .setCH(uaCH) + .parseCH() + .get(); + }; + this.set(BROWSER, parse(BROWSER)) + .set(CPU, parse(CPU)) + .set(DEVICE, parse(DEVICE)) + .set(ENGINE, parse(ENGINE)) + .set(OS, parse(OS)); + } + return this; + }; + function UAParser (ua, extensions, headers) { if (typeof ua === TYPEOF.OBJECT) {