Skip to content

Commit a9dd8e7

Browse files
committed
fix: #3141 help(config) altering the actual config when evaluating the examples
1 parent ac1fc2f commit a9dd8e7

File tree

4 files changed

+29
-5
lines changed

4 files changed

+29
-5
lines changed

HISTORY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
for the option `wordSize` in the functions `hex`, `bin`, and `oct`.
1515
- Fix: #3125 type definitions of function `hypot` (#3144).
1616
Thanks @silentmissile.
17+
- Fix: #3141 `help(config)` altering the actual `config` when evaluating the
18+
examples.
1719
- Docs: #3145 fix documentation about REPL, it does require a build step
1820
nowadays.
1921

src/expression/Help.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { format } from '../utils/string.js'
44
import { factory } from '../utils/factory.js'
55

66
const name = 'Help'
7-
const dependencies = ['parse']
7+
const dependencies = ['evaluate']
88

9-
export const createHelpClass = /* #__PURE__ */ factory(name, dependencies, ({ parse }) => {
9+
export const createHelpClass = /* #__PURE__ */ factory(name, dependencies, ({ evaluate }) => {
1010
/**
1111
* Documentation object
1212
* @param {Object} doc Object containing properties:
@@ -58,15 +58,26 @@ export const createHelpClass = /* #__PURE__ */ factory(name, dependencies, ({ pa
5858
if (doc.examples) {
5959
desc += 'Examples:\n'
6060

61-
const scope = {}
61+
// after evaluating the examples, we restore config in case the examples
62+
// did change the config.
63+
let configChanged = false
64+
const originalConfig = evaluate('config()')
65+
66+
const scope = {
67+
config: (newConfig) => {
68+
configChanged = true
69+
return evaluate('config(newConfig)', { newConfig })
70+
}
71+
}
72+
6273
for (let i = 0; i < doc.examples.length; i++) {
6374
const expr = doc.examples[i]
6475
desc += ' ' + expr + '\n'
6576

6677
let res
6778
try {
6879
// note: res can be undefined when `expr` is an empty string
69-
res = parse(expr).compile().evaluate(scope)
80+
res = evaluate(expr, scope)
7081
} catch (e) {
7182
res = e
7283
}
@@ -75,6 +86,10 @@ export const createHelpClass = /* #__PURE__ */ factory(name, dependencies, ({ pa
7586
}
7687
}
7788
desc += '\n'
89+
90+
if (configChanged) {
91+
evaluate('config(originalConfig)', { originalConfig })
92+
}
7893
}
7994
if (doc.mayThrow && doc.mayThrow.length) {
8095
desc += 'Throws: ' + doc.mayThrow.join(', ') + '\n\n'

test/generated-code-tests/entry/mainAny.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ describe('mainAny', function () {
119119
assert.deepStrictEqual(scope, { b: 2 })
120120
})
121121

122-
it('should evaluate assignement and access', function () {
122+
it('should evaluate assignment and access', function () {
123123
const math = create(all)
124124
const evaluate = math.evaluate
125125

test/unit-tests/expression/function/help.test.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ describe('help', function () {
2626
assert.strictEqual(help.doc.name, 'sin')
2727
})
2828

29+
it('should not alter the mathjs instance when stringifying help', function () {
30+
const config = math.config()
31+
const str = math.help(math.config).toString()
32+
assert(str.includes('number: "Fraction"'))
33+
assert.deepStrictEqual(math.config(), config)
34+
})
35+
2936
it('should find help from a function', function () {
3037
const help = math.help(math.sin)
3138
assert(help instanceof math.Help)

0 commit comments

Comments
 (0)