Skip to content

Release 0.6.0 🚀 - #23

Merged
NetWin merged 9 commits into
masterfrom
increment
Oct 25, 2026
Merged

NetWin merged 9 commits into
masterfrom
increment

Conversation

@NetWin

@NetWin NetWin commented Oct 25, 2026 •

Copy link
Copy Markdown
Owner

Summary

Releases everything merged into increment since 0.5.1:

Highlights

  • WeakMap and WeakSet. Scripts can cache results per object or track visited objects. WeakMap has get, set, has and delete; WeakSet has add, has and delete. The constructors take an iterable and require new, and a primitive key throws V8's TypeError: Invalid value used as weak map key / Invalid value used in weak set. Any object can be a key, including functions and built-ins such as Math. Both are backed by host weak collections, so entries keyed by throwaway objects can be collected during a long run. Until now reading either name threw DISALLOWED_SYNTAX.
  • Built-in properties follow JavaScript's rules. A function's name and length can be deleted, after which they read '' and 0 from Function.prototype. Built-in methods such as Math.max or JSON.parse can be replaced and deleted, while constants such as Math.PI still can be neither. An error's name, message and stack can be deleted, and String(e) and the error the host receives use what remains. Whatever a run replaces or deletes on a shared built-in stays in that run; nested runs and the next run see the originals.
  • Type accessors live on the prototype. A Map's or Set's size and a RegExp's source and flags still answer and in still finds them, but Object.hasOwn and Object.getOwnPropertyNames leave them out, as in JavaScript: new Map() lists [] and /a/g lists ['lastIndex'].
  • new Map(iterable) accepts any object as an entry. It reads entry[0] and entry[1] like Object.fromEntries does, so new Map([{ 0: 'a', 1: 1 }]) works. Before, every entry that was not an array threw.

Behaviour changes for hosts

  • A weak collection can't cross the boundary, since its entries can't be listed. Passed in with data or globals, or returned from a host function, it is rejected like any other unsupported value. Leaving the run it becomes undefined, and passed to a host function it throws a catchable TypeError: A WeakMap cannot be passed to the host, as an iterator does.
  • An error whose message or name a script deleted reaches the host with '' / the constructor's name.
  • Scripts that relied on the old behaviour see these changes:
    • Assigning to a built-in method (Math.max = fn) no longer throws.
    • delete f.name is no longer a no-op, and delete r.lastIndex now throws.
    • Deleting a constant throws V8's message, Cannot delete property 'PI' of #<Object>, instead of "of a read-only object".
    • Object.hasOwn(map, 'size') and similar checks on type accessors now return false.
    • Object.preventExtensions(Math) no longer makes Object.isSealed(Math) and Object.isFrozen(Math) report true.

Divergences

No new divergence from JavaScript. The parity package gained divergences where Maple follows JavaScript and js-interpreter (ES5) does not: delete f.name, deleting Math.PI or lastIndex, Object.getOwnPropertyNames on a RegExp and delete r.source.

Tooling

  • The parity helpers run Node last, so a case that changes a built-in can restore it in a finally before anything else runs. AGENTS.md notes the rule.

NetWin and others added 9 commits October 24, 2026 15:33
WeakMap and WeakSet were rejected as host-only names. They are now
standard globals backed by host weak collections, with the spec surface
and V8 messages. Any object is a valid key. A weak collection cannot
enter a run, and leaves it as undefined, like an iterator.
new Map(iterable) refused every entry that was not an array, and
read entry[0] and entry[1] off the host array directly. It now reads
both through the member model, as Object.fromEntries does, so
{ 0: key, 1: value } and Maple's own objects work as in JavaScript.
Node runs each case in the test process, so a case that replaces or
deletes a built-in changes it for js-interpreter and Maple too. Every
helper now runs Node last, and such a case restores the built-in in a
finally before anything else runs.
A Map's or Set's size and a RegExp's source and flags are accessors on
the prototype in JavaScript, not own properties. Every value still
answers to them and in finds them, but Object.hasOwn and
Object.getOwnPropertyNames now leave them out, and deleting one changes
nothing. lastIndex stays a RegExp's one own property.
… properties

As in JavaScript, a function's name and length can be deleted, which
leaves what Function.prototype has, and the methods of a built-in such as
Math.max can be replaced and deleted, while constants such as Math.PI and
a RegExp's lastIndex cannot be deleted. An error's name, message and
stack can be deleted too. What a run changes on a shared built-in stays
in that run.
Let scripts delete and replace built-in properties where JavaScript allows it
@github-actions

Copy link
Copy Markdown

📋 Release Preview

Changelog

0.6.0 (2026-10-25)

🚀 Features

  • builtins: support WeakMap and WeakSet (4e1af2e)

🩹 Bug Fixes

  • map: read constructor entries as any object, not only arrays (91eb05e)
  • properties: let scripts delete and replace configurable built-in properties (2f1ef57)
  • properties: stop listing type accessors as own properties (b4d9048)

🧪 Tests

  • parity: run Node last so a case can restore what it changes (c726ab5)

@NetWin
NetWin merged commit 04f64fe into master Oct 25, 2026
8 checks passed
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 0.6.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant