From f94a77bf3012da741e896ad841c35c1ea0588ac9 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Fri, 15 Aug 2025 17:40:49 +0200 Subject: [PATCH 1/4] feat: added Function.isFunction() static method --- core/extras/function.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/core/extras/function.js b/core/extras/function.js index 99fb4faa1..b5f375672 100644 --- a/core/extras/function.js +++ b/core/extras/function.js @@ -77,3 +77,26 @@ Object.defineProperty(Function.prototype, "isClass", { configurable: true }); + +if (typeof Function.isFunction === "undefined") { + /** + * Function.isFunction() - Determines if a value is a function + * + * Adds a static method to the Function constructor that determines whether the passed + * value is a function. This method provides functionality similar to `Array.isArray()` + * but specifically for function types. + * + * This method detects all types of functions including regular functions, arrow functions, + * async functions, generator functions, class constructors, and built-in functions. + * + * Only adds the method if it doesn't already exist, ensuring + * compatibility with environments that may implement this method natively in the future. + * + * @function external:Function.isFunction + * @param {*} value - The value to test. Can be any JavaScript value. + * @returns {boolean} Returns `true` if the value is any type of function + */ + Function.isFunction = function (value) { + return typeof value === "function"; + }; +} From fab35f898e3e123eced7b493f63816f127a66e59 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Fri, 15 Aug 2025 17:41:33 +0200 Subject: [PATCH 2/4] feat: added String.isString() static method --- core/extras/string.js | 18 ++++++++++++++++++ core/mini-url.js | 15 ++++++--------- data/service/data-service.js | 5 +++-- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/core/extras/string.js b/core/extras/string.js index ebd42ba65..dd5f6ef92 100644 --- a/core/extras/string.js +++ b/core/extras/string.js @@ -301,3 +301,21 @@ if(typeof String.prototype.substringWithinRange !== "function") { } +if (typeof String.isString === "undefined") { + /** + * String.isString() - Determines if a value is a string primitive or String object. + * + * Adds a static method to the String constructor that determines whether the passed + * value is a string primitive or String object instance. This method provides + * functionality similar to `Array.isArray()` but specifically for string types. + * + * Only adds the method if it doesn't already exist, ensuring + * compatibility with environments that may implement this method natively in the future. + * @function external:String.isString + * @param {*} value - The value to test. Can be any JavaScript value. + * @returns {boolean} Returns `true` if the value is a string primitive or String object + */ + String.isString = function (value) { + return typeof value === "string" || value instanceof String; + }; +} diff --git a/core/mini-url.js b/core/mini-url.js index c7595ebde..ef0166d0d 100644 --- a/core/mini-url.js +++ b/core/mini-url.js @@ -181,9 +181,6 @@ function isNullOrUndefined(value) { return value === null || value === undefined; } -function isString(str) { - return typeof str === 'string'; -} function isObject(obj) { return typeof obj === 'object'; @@ -196,12 +193,12 @@ function urlParse(url, parseQueryString, slashesDenoteHost) { var u = new Url; u.parse(url, parseQueryString, slashesDenoteHost); - + return u; } Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { - if (!isString(url)) { + if (!String.isString(url)) { throw new TypeError("Parameter 'url' must be a string, not " + typeof url); } @@ -471,14 +468,14 @@ function urlFormat(obj) { // If it's an obj, this is a no-op. // this way, you can call url_format() on strings // to clean up potentially wonky urls. - if (isString(obj)) { + if (String.isString(obj)) { obj = urlParse(obj); } if (!(obj instanceof Url)) { return Url.prototype.format.call(obj); } else { - return obj.format(); + return obj.format(); } } @@ -563,7 +560,7 @@ function urlResolveObject(source, relative) { } Url.prototype.resolveObject = function(relative) { - if (isString(relative)) { + if (String.isString(relative)) { var rel = new Url(); rel.parse(relative, false, true); relative = rel; @@ -871,4 +868,4 @@ Url.prototype.parseHost = function() { exports.resolve = function(source, relative) { return urlParse(source, false, true).resolve(relative); -}; \ No newline at end of file +}; diff --git a/data/service/data-service.js b/data/service/data-service.js index 0ec5f1348..2d1047e27 100644 --- a/data/service/data-service.js +++ b/data/service/data-service.js @@ -6920,9 +6920,10 @@ DataService.addClassProperties({ _getOfflineOperationMethodName: { value: function(type) { - var isString = typeof type === "string", + var isString = String.isString(type), name = isString && this._offlineOperationMethodNames.get(type); - if (isString && !name) { + + if (String.isString(type) && !name) { name = "perform"; name += type[0].toUpperCase(); name += type.slice(1); From 4655420eaf515d9992043d3e174e248378a2554a Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Fri, 15 Aug 2025 17:42:23 +0200 Subject: [PATCH 3/4] refactor: Object.isObject() static method --- core/collections/shim-object.js | 14 +----- .../collections/test/spec/shim-object-spec.js | 21 --------- core/extras/object.js | 44 +++++++++++++++++++ core/mini-url.js | 9 +--- 4 files changed, 47 insertions(+), 41 deletions(-) diff --git a/core/collections/shim-object.js b/core/collections/shim-object.js index f1a4d70f8..a3d710a46 100644 --- a/core/collections/shim-object.js +++ b/core/collections/shim-object.js @@ -1,5 +1,6 @@ "use strict"; +require("/core/extras/object"); require("./shim-function"); module.exports = Object; @@ -24,19 +25,6 @@ module.exports = Object; */ Object.empty = Object.freeze(Object.create(null)); -/** - Returns whether the given value is an object, as opposed to a value. - Unboxed numbers, strings, true, false, undefined, and null are not - objects. Arrays are objects. - - @function external:Object.isObject - @param {Any} value - @returns {Boolean} whether the given value is an object -*/ -Object.isObject = function (object) { - return Object(object) === object; -}; - /** Returns the value of an any value, particularly objects that implement valueOf. diff --git a/core/collections/test/spec/shim-object-spec.js b/core/collections/test/spec/shim-object-spec.js index c41dbf25d..d8b0986f4 100644 --- a/core/collections/test/spec/shim-object-spec.js +++ b/core/collections/test/spec/shim-object-spec.js @@ -40,27 +40,6 @@ describe("ObjectShim-spec", function () { }); - describe("isObject", function () { - - [ - ["null is not an object", null, false], - ["numbers are not objects", 1, false], - ["undefined is not an object", undefined, false], - ["arrays are objects", [], true], - ["object literals are objects", {}, true], - [ - "pure objects (null prototype) are", - Object.create(null), - true - ] - ].forEach(function (test) { - it("should recognize that " + test[0], function () { - expect(Object.isObject(test[1])).toEqual(test[2]); - }); - }); - - }); - describe("getValueOf", function () { var fakeNumber = Object.create({ valueOf: function () { diff --git a/core/extras/object.js b/core/extras/object.js index 977ba1ab7..908c46ab0 100644 --- a/core/extras/object.js +++ b/core/extras/object.js @@ -121,3 +121,47 @@ if (Object.prototype.hasOwnProperty('isEmpty') === false) { enumerable: false }); } + +if (typeof Object.isObject === "undefined") { + /** + * Object.isObject() - General plain object check with optional strict mode + * + * Determines whether the passed value is an object, with two modes of checking: + * - Default mode: Returns true for any non-null object (including arrays, dates, etc.) + * - Strict mode: Returns true only for plain objects using toString() method + * + * In strict mode, this matches objects created with {}, new Object(), + * Object.create(Object.prototype), and similar plain object patterns. + * + * @function external:Object.isObject + * @param {*} value - The value to test. Can be any JavaScript value. + * @param {boolean} [strict=false] - If true, performs strict plain object check using toString() + * @returns {boolean} Returns `true` if the value passes the object check, `false` otherwise + * + * @example + * // Default mode - any non-null object + * Object.isObject({}); // true + * Object.isObject([]); // true + * Object.isObject(new Date()); // true + * Object.isObject(null); // false + * Object.isObject("string"); // false + * + * @example + * // Strict mode - plain objects only + * Object.isObject({}, true); // true + * Object.isObject(new Object(), true); // true + * Object.isObject(Object.create(Object.prototype), true); // true + * Object.isObject([], true); // false + * Object.isObject(new Date(), true); // false + * Object.isObject(null, true); // false + */ + Object.isObject = function (value, strict = false) { + if (value === null || typeof value !== "object") return false; + + if (strict) { + return Object.prototype.toString.call(value) === "[object Object]"; + } + + return true; + }; +} diff --git a/core/mini-url.js b/core/mini-url.js index ef0166d0d..876de262a 100644 --- a/core/mini-url.js +++ b/core/mini-url.js @@ -181,13 +181,8 @@ function isNullOrUndefined(value) { return value === null || value === undefined; } - -function isObject(obj) { - return typeof obj === 'object'; -} - function urlParse(url, parseQueryString, slashesDenoteHost) { - if (url && isObject(url) && url instanceof Url) { + if (url && Object.isObject(url) && url instanceof Url) { return url; } @@ -505,7 +500,7 @@ Url.prototype.format = function() { } if (this.query && - isObject(this.query) && + Object.isObject(this.query) && Object.keys(this.query).length) { query = encodeQuerystring(this.query); } From 49550ac231b5932aa1b15040c9e3922d84be3a98 Mon Sep 17 00:00:00 2001 From: Thibault Zanini Date: Fri, 15 Aug 2025 17:42:55 +0200 Subject: [PATCH 4/4] feat: added Object.isPureObject() static method --- core/extras/object.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/extras/object.js b/core/extras/object.js index 908c46ab0..b3ffaacf2 100644 --- a/core/extras/object.js +++ b/core/extras/object.js @@ -165,3 +165,31 @@ if (typeof Object.isObject === "undefined") { return true; }; } + +if (typeof Object.isPureObject === "undefined") { + /** + * Object.isPureObject() - Objects without custom prototype pollution + * + * Determines whether the passed value is a pure object by checking its prototype. + * Only accepts objects with Object.prototype or null as their direct prototype. + * This excludes objects created with custom constructors or Object.create() with + * custom prototypes. + * + * @function external:Object.isPureObject + * @param {*} value - The value to test. Can be any JavaScript value. + * @returns {boolean} Returns `true` if the value is a pure object, `false` otherwise + * + * @example + * Object.isPureObject({}); // true + * Object.isPureObject(new Object()); // true + * Object.isPureObject(Object.create(null)); // true + * Object.isPureObject(Object.create({})); // false + * Object.isPureObject(new Date()); // false + */ + Object.isPureObject = function (value) { + if (!Object.isObject(value)) return false; + + return Object.getPrototypeOf(value) === Object.prototype || + Object.getPrototypeOf(value) === null; + }; +}