* A `Namespace` refers to a space of nameable things like macros or lengths, * which can be `set` either globally or local to a nested group, using an * undo stack similar to how TeX implements this functionality. * Performance-wise, `get` and local `set` take constant time, while global * `set`
| 12901 | * `set` takes time proportional to the depth of group nesting. |
| 12902 | */ |
| 12903 | class Namespace { |
| 12904 | /** |
| 12905 | * Both arguments are optional. The first argument is an object of |
| 12906 | * built-in mappings which never change. The second argument is an object |
| 12907 | * of initial (global-level) mappings, which will constantly change |
| 12908 | * according to any global/top-level `set`s done. |
| 12909 | */ |
| 12910 | constructor(builtins, globalMacros) { |
| 12911 | if (builtins === void 0) { |
| 12912 | builtins = {}; |
| 12913 | } |
| 12914 | |
| 12915 | if (globalMacros === void 0) { |
| 12916 | globalMacros = {}; |
| 12917 | } |
| 12918 | |
| 12919 | this.current = void 0; |
| 12920 | this.builtins = void 0; |
| 12921 | this.undefStack = void 0; |
| 12922 | this.current = globalMacros; |
| 12923 | this.builtins = builtins; |
| 12924 | this.undefStack = []; |
| 12925 | } |
| 12926 | /** |
| 12927 | * Start a new nested group, affecting future local `set`s. |
| 12928 | */ |
| 12929 | |
| 12930 | |
| 12931 | beginGroup() { |
| 12932 | this.undefStack.push({}); |
| 12933 | } |
| 12934 | /** |
| 12935 | * End current nested group, restoring values before the group began. |
| 12936 | */ |
| 12937 | |
| 12938 | |
| 12939 | endGroup() { |
| 12940 | if (this.undefStack.length === 0) { |
| 12941 | throw new ParseError("Unbalanced namespace destruction: attempt " + "to pop global namespace; please report this as a bug"); |
| 12942 | } |
| 12943 | |
| 12944 | const undefs = this.undefStack.pop(); |
| 12945 | |
| 12946 | for (const undef in undefs) { |
| 12947 | if (undefs.hasOwnProperty(undef)) { |
| 12948 | if (undefs[undef] === undefined) { |
| 12949 | delete this.current[undef]; |
| 12950 | } else { |
| 12951 | this.current[undef] = undefs[undef]; |
| 12952 | } |
| 12953 | } |
| 12954 | } |
| 12955 | } |
| 12956 | /** |
| 12957 | * Detect whether `name` has a definition. Equivalent to |
| 12958 | * `get(name) != null`. |
| 12959 | */ |
| 12960 |
nothing calls this directly
no outgoing calls
no test coverage detected