Files
2023-08-01 13:49:46 +02:00

123 lines
3.6 KiB
JavaScript

/**
* @file Converts a JavaScript object to a primitive value.
* @version 1.1.0
* @author Xotic750 <Xotic750@gmail.com>
* @copyright Xotic750
* @license {@link <https://opensource.org/licenses/MIT> MIT}
* @module to-primitive-x
*/
'use strict';
var hasSymbols = require('has-symbol-support-x');
var isPrimitive = require('is-primitive');
var isDate = require('is-date-object');
var isSymbol = require('is-symbol');
var isFunction = require('is-function-x');
var requireObjectCoercible = require('require-object-coercible-x');
var isNil = require('is-nil-x');
var isUndefined = require('validate.io-undefined');
var symToPrimitive = hasSymbols && Symbol.toPrimitive;
var symValueOf = hasSymbols && Symbol.prototype.valueOf;
var toStringOrder = ['toString', 'valueOf'];
var toNumberOrder = ['valueOf', 'toString'];
var orderLength = 2;
var ordinaryToPrimitive = function _ordinaryToPrimitive(O, hint) {
requireObjectCoercible(O);
if (typeof hint !== 'string' || (hint !== 'number' && hint !== 'string')) {
throw new TypeError('hint must be "string" or "number"');
}
var methodNames = hint === 'string' ? toStringOrder : toNumberOrder;
var method;
var result;
for (var i = 0; i < orderLength; i += 1) {
method = O[methodNames[i]];
if (isFunction(method)) {
result = method.call(O);
if (isPrimitive(result)) {
return result;
}
}
}
throw new TypeError('No default value');
};
var getMethod = function _getMethod(O, P) {
var func = O[P];
if (isNil(func) === false) {
if (isFunction(func) === false) {
throw new TypeError(func + ' returned for property ' + P + ' of object ' + O + ' is not a function');
}
return func;
}
return void 0;
};
// http://www.ecma-international.org/ecma-262/6.0/#sec-toprimitive
/**
* This method converts a JavaScript object to a primitive value.
* Note: When toPrimitive is called with no hint, then it generally behaves as
* if the hint were Number. However, objects may over-ride this behaviour by
* defining a @@toPrimitive method. Of the objects defined in this specification
* only Date objects (see 20.3.4.45) and Symbol objects (see 19.4.3.4) over-ride
* the default ToPrimitive behaviour. Date objects treat no hint as if the hint
* were String.
*
* @param {*} input - The input to convert.
* @param {constructor} [prefferedtype] - The preffered type (String or Number).
* @throws {TypeError} If unable to convert input to a primitive.
* @returns {string|number} The converted input as a primitive.
* @example
* var toPrimitive = require('to-primitive-x');
*
* var date = new Date(0);
* toPrimitive(date)); // Thu Jan 01 1970 01:00:00 GMT+0100 (CET)
* toPrimitive(date, String)); // Thu Jan 01 1970 01:00:00 GMT+0100 (CET)
* toPrimitive(date, Number)); // 0
*/
module.exports = function toPrimitive(input, preferredType) {
if (isPrimitive(input)) {
return input;
}
var hint = 'default';
if (arguments.length > 1) {
if (preferredType === String) {
hint = 'string';
} else if (preferredType === Number) {
hint = 'number';
}
}
var exoticToPrim;
if (hasSymbols) {
if (symToPrimitive) {
exoticToPrim = getMethod(input, symToPrimitive);
} else if (isSymbol(input)) {
exoticToPrim = symValueOf;
}
}
if (isUndefined(exoticToPrim) === false) {
var result = exoticToPrim.call(input, hint);
if (isPrimitive(result)) {
return result;
}
throw new TypeError('unable to convert exotic object to primitive');
}
if (hint === 'default' && (isDate(input) || isSymbol(input))) {
hint = 'string';
}
return ordinaryToPrimitive(input, hint === 'default' ? 'number' : hint);
};