ApplyStringOrNumericBinaryOperator.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. 'use strict';
  2. var $TypeError = require('es-errors/type');
  3. var HasOwnProperty = require('./HasOwnProperty');
  4. var ToNumeric = require('./ToNumeric');
  5. var ToPrimitive = require('./ToPrimitive');
  6. var ToString = require('./ToString');
  7. var Type = require('./Type');
  8. var NumberAdd = require('./Number/add');
  9. var NumberBitwiseAND = require('./Number/bitwiseAND');
  10. var NumberBitwiseOR = require('./Number/bitwiseOR');
  11. var NumberBitwiseXOR = require('./Number/bitwiseXOR');
  12. var NumberDivide = require('./Number/divide');
  13. var NumberExponentiate = require('./Number/exponentiate');
  14. var NumberLeftShift = require('./Number/leftShift');
  15. var NumberMultiply = require('./Number/multiply');
  16. var NumberRemainder = require('./Number/remainder');
  17. var NumberSignedRightShift = require('./Number/signedRightShift');
  18. var NumberSubtract = require('./Number/subtract');
  19. var NumberUnsignedRightShift = require('./Number/unsignedRightShift');
  20. var BigIntAdd = require('./BigInt/add');
  21. var BigIntBitwiseAND = require('./BigInt/bitwiseAND');
  22. var BigIntBitwiseOR = require('./BigInt/bitwiseOR');
  23. var BigIntBitwiseXOR = require('./BigInt/bitwiseXOR');
  24. var BigIntDivide = require('./BigInt/divide');
  25. var BigIntExponentiate = require('./BigInt/exponentiate');
  26. var BigIntLeftShift = require('./BigInt/leftShift');
  27. var BigIntMultiply = require('./BigInt/multiply');
  28. var BigIntRemainder = require('./BigInt/remainder');
  29. var BigIntSignedRightShift = require('./BigInt/signedRightShift');
  30. var BigIntSubtract = require('./BigInt/subtract');
  31. var BigIntUnsignedRightShift = require('./BigInt/unsignedRightShift');
  32. // https://262.ecma-international.org/12.0/#sec-applystringornumericbinaryoperator
  33. // https://262.ecma-international.org/12.0/#step-applystringornumericbinaryoperator-operations-table
  34. var table = {
  35. '**': [NumberExponentiate, BigIntExponentiate],
  36. '*': [NumberMultiply, BigIntMultiply],
  37. '/': [NumberDivide, BigIntDivide],
  38. '%': [NumberRemainder, BigIntRemainder],
  39. '+': [NumberAdd, BigIntAdd],
  40. '-': [NumberSubtract, BigIntSubtract],
  41. '<<': [NumberLeftShift, BigIntLeftShift],
  42. '>>': [NumberSignedRightShift, BigIntSignedRightShift],
  43. '>>>': [NumberUnsignedRightShift, BigIntUnsignedRightShift],
  44. '&': [NumberBitwiseAND, BigIntBitwiseAND],
  45. '^': [NumberBitwiseXOR, BigIntBitwiseXOR],
  46. '|': [NumberBitwiseOR, BigIntBitwiseOR]
  47. };
  48. module.exports = function ApplyStringOrNumericBinaryOperator(lval, opText, rval) {
  49. if (typeof opText !== 'string' || !HasOwnProperty(table, opText)) {
  50. throw new $TypeError('Assertion failed: `opText` must be a valid operation string');
  51. }
  52. if (opText === '+') {
  53. var lprim = ToPrimitive(lval);
  54. var rprim = ToPrimitive(rval);
  55. if (typeof lprim === 'string' || typeof rprim === 'string') {
  56. var lstr = ToString(lprim);
  57. var rstr = ToString(rprim);
  58. return lstr + rstr;
  59. }
  60. /* eslint no-param-reassign: 1 */
  61. lval = lprim;
  62. rval = rprim;
  63. }
  64. var lnum = ToNumeric(lval);
  65. var rnum = ToNumeric(rval);
  66. var T = Type(lnum);
  67. if (T !== Type(rnum)) {
  68. throw new $TypeError('types of ' + lnum + ' and ' + rnum + ' differ');
  69. }
  70. var Operation = table[opText][T === 'BigInt' ? 1 : 0];
  71. return Operation(lnum, rnum);
  72. };