@opencode/codemode 0.0.0-dev-19618 → 0.0.0-dev-19619

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/data.d.ts CHANGED
@@ -23,5 +23,10 @@ export declare const fromData: (protos: Prototypes, value: unknown, label: strin
23
23
  * non-finite numbers become null, and array holes become null. `undefined` object properties are
24
24
  * dropped ("json") or become null ("result", for program results where the consumer must never see
25
25
  * undefined); a bare `undefined` follows the same rule.
26
+ *
27
+ * At the host boundary (tool arguments and program results) `__proto__` keys are dropped and values
28
+ * `JSON.stringify` would flatten to `{}` cross in a useful form instead: a Set as an array, a RegExp
29
+ * and URLSearchParams as their strings. `JSON.stringify` itself passes `boundary: false` to keep JS
30
+ * behavior.
26
31
  */
27
- export declare const toData: (value: unknown, label: string, undefinedAs?: "json" | "result", stripProto?: boolean) => unknown;
32
+ export declare const toData: (value: unknown, label: string, undefinedAs?: "json" | "result", boundary?: boolean) => unknown;
package/dist/data.js CHANGED
@@ -27,10 +27,15 @@ export const fromData = (protos, value, label) => copy(value, label, "data", 0,
27
27
  * non-finite numbers become null, and array holes become null. `undefined` object properties are
28
28
  * dropped ("json") or become null ("result", for program results where the consumer must never see
29
29
  * undefined); a bare `undefined` follows the same rule.
30
+ *
31
+ * At the host boundary (tool arguments and program results) `__proto__` keys are dropped and values
32
+ * `JSON.stringify` would flatten to `{}` cross in a useful form instead: a Set as an array, a RegExp
33
+ * and URLSearchParams as their strings. `JSON.stringify` itself passes `boundary: false` to keep JS
34
+ * behavior.
30
35
  */
31
- export const toData = (value, label, undefinedAs = "json", stripProto = true) => copy(value, label, undefinedAs, 0, new Set(), undefined, stripProto);
32
- const copy = (value, label, mode, depth, seen, protos, stripProto = true) => {
33
- const next = (item) => copy(item, label, mode, depth + 1, seen, protos, stripProto);
36
+ export const toData = (value, label, undefinedAs = "json", boundary = true) => copy(value, label, undefinedAs, 0, new Set(), undefined, boundary);
37
+ const copy = (value, label, mode, depth, seen, protos, boundary = true) => {
38
+ const next = (item) => copy(item, label, mode, depth + 1, seen, protos, boundary);
34
39
  if (depth > MAX_VALUE_DEPTH) {
35
40
  throw new ToolRuntimeError("InvalidDataValue", `${label} exceeds the maximum value depth of ${MAX_VALUE_DEPTH}.`);
36
41
  }
@@ -88,6 +93,20 @@ const copy = (value, label, mode, depth, seen, protos, stripProto = true) => {
88
93
  return value.url.href;
89
94
  if (value instanceof URL)
90
95
  return value.href;
96
+ if (boundary && protos === undefined) {
97
+ if (value instanceof ProgramRegExp)
98
+ return String(value.regex);
99
+ if (value instanceof ProgramURLSearchParams)
100
+ return value.params.toString();
101
+ if (value instanceof ProgramSet) {
102
+ if (seen.has(value))
103
+ throw new ToolRuntimeError("InvalidDataValue", `${label} contains a circular value.`);
104
+ seen.add(value);
105
+ const copied = Array.from(value.set, (item) => next(item) ?? null);
106
+ seen.delete(value);
107
+ return copied;
108
+ }
109
+ }
91
110
  // Remaining wrappers and their host counterparts serialize as empty objects, like JSON.stringify.
92
111
  if (isWrapper(value) ||
93
112
  value instanceof RegExp ||
@@ -113,7 +132,7 @@ const copy = (value, label, mode, depth, seen, protos, stripProto = true) => {
113
132
  defineHost(copied, "message", next(get(value, "message")));
114
133
  }
115
134
  for (const [key, item] of entries(value)) {
116
- if (stripProto && key === "__proto__")
135
+ if (boundary && key === "__proto__")
117
136
  continue;
118
137
  const copiedItem = next(item);
119
138
  if (copiedItem === undefined && mode === "json")
@@ -150,7 +169,7 @@ const copy = (value, label, mode, depth, seen, protos, stripProto = true) => {
150
169
  }
151
170
  const copied = {};
152
171
  for (const [key, item] of Object.entries(value)) {
153
- if (stripProto && key === "__proto__")
172
+ if (boundary && key === "__proto__")
154
173
  continue;
155
174
  const copiedItem = next(item);
156
175
  if (copiedItem === undefined && mode === "json")
@@ -54,7 +54,7 @@ const stringify = (runner, args) => {
54
54
  .filter((item) => typeof item === "string" || typeof item === "number")
55
55
  .map(String)
56
56
  : null;
57
- // A string cannot pollute, so __proto__ stays: JSON.stringify includes own __proto__ keys, like JS.
57
+ // Not a host boundary: __proto__ stays and Set/RegExp/URLSearchParams serialize as {}, like JS.
58
58
  const text = JSON.stringify(toData(args[0], "JSON.stringify value", "json", false), properties, indent);
59
59
  if (text !== undefined)
60
60
  checkStringLength(text.length);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@opencode/codemode",
4
- "version": "0.0.0-dev-19618",
4
+ "version": "0.0.0-dev-19619",
5
5
  "description": "Effect-native confined code execution over schema-described tools",
6
6
  "type": "module",
7
7
  "license": "MIT",