MikeMcl / decimal.js

An arbitrary-precision Decimal type for JavaScript
http://mikemcl.github.io/decimal.js
MIT License
6.45k stars 475 forks source link

cos() throws TypeError #140

Closed AlienKevin closed 3 years ago

AlienKevin commented 5 years ago

Issue

When I call new Decima(1).cos(), node outputs the following error message:

TypeError: Cannot assign to read only property 'precision' of function 'function Decimal(v) {
      var e, i, t,
        x = this;

      // Decimal called without new.
      if ...<omitted>... }'

Error Location

The error happens in the line below in P.cosine function when I run the debugger:

P.cosine = P.cos = function () {
    var pr, rm,
      x = this,
      Ctor = x.constructor;

    if (!x.d) return new Ctor(NaN);

    // cos(0) = cos(-0) = 1
    if (!x.d[0]) return new Ctor(1);

    pr = Ctor.precision;
    rm = Ctor.rounding;
    >>> Ctor.precision = pr + Math.max(x.e, x.sd()) + LOG_BASE; <<<
    Ctor.rounding = 1;

Temporary Solution

After I removed the 'use strict'; at the top of decimal.js, the error goes away.

Related issue

It seems that the issue "Exception-safety of methods that temporarily mutate settings" is still not addressed and the cosine function is still modifying the global Decimal constructor which throws a TypeError under strict mode. Also, by extension all trig functions including sin, cos, tan, asin, acos, atan throws TypeError for assigning to readonly 'precision' property.

MikeMcl commented 5 years ago

test.js

const Decimal = require('decimal.js');
const c = new Decimal(1).cos();
console.log(c.toString());
$ node test
0.5403023058681397174

For me to be able to help you, you need to provide more details about the JavaScript environment and code context. This library does not make precision a read-only property of Decimal.

It seems that the issue "Exception-safety of methods that temporarily mutate settings" is still not addressed and the cosine function is still modifying the global Decimal constructor which throws a TypeError under strict mode.

No, it doesn't normally throw an error.

If you want to try an amended version of the library that does not temporarily mutate settings, but is not as well tested, try

decimal.zip

AlienKevin commented 5 years ago

I just found out why the error happens. My project is compiled from TypeScript so all export properties are wrapped in Object.defineProperty which automatically sets the writable attribute of objects defined inside to false. Hence the TypeError when decimal.js tries to reassign precision. Here's the line that causes the problem:

Object.defineProperty(exports, "__esModule", { value: true });

This is not a decimal.js problem. However, do you know any workaround for people using TypeScript?