@temperlang/core 0.4.0 → 0.5.0

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/async.js CHANGED
File without changes
package/bitvector.js CHANGED
File without changes
package/check-type.js CHANGED
File without changes
package/core.js CHANGED
@@ -98,6 +98,13 @@ export const bubble = () => {
98
98
  throw Error();
99
99
  };
100
100
 
101
+ /**
102
+ * TODO Distinguish panic from bubble.
103
+ *
104
+ * @returns {never}
105
+ */
106
+ export const panic = bubble;
107
+
101
108
  /**
102
109
  * @template T
103
110
  * @param {T} a
@@ -105,3 +112,75 @@ export const bubble = () => {
105
112
  export const print = (a) => {
106
113
  console.log("%s", a);
107
114
  };
115
+
116
+ /**
117
+ * Takes a JSON adapter and a value that it can adapt.
118
+ * This is called when JavaScript code calls JSON.stringify on a Temper type instance
119
+ * that has a zero argument jsonAdapter static method.
120
+ *
121
+ * @return any
122
+ */
123
+ export let marshalToJsonObject = (jsonAdapter, value) => {
124
+ let stack = [[]];
125
+ let pendingKey = null;
126
+ function store(value) {
127
+ let top = stack[stack.length - 1];
128
+ if (pendingKey !== null) {
129
+ top[pendingKey] = value;
130
+ pendingKey = null;
131
+ } else if (Array.isArray(top)) {
132
+ top.push(value);
133
+ } else {
134
+ throw new Error();
135
+ }
136
+ }
137
+ let jsonProducer = {
138
+ interchangeContext: { getHeader() { return null; } },
139
+
140
+ startObject() {
141
+ let o = {};
142
+ store(o);
143
+ stack.push(o);
144
+ },
145
+ endObject() { stack.pop(); },
146
+ objectKey(key) { pendingKey = String(key); },
147
+
148
+ startArray() {
149
+ let a = [];
150
+ store(a);
151
+ stack.push(a);
152
+ },
153
+ endArray() { stack.pop(); },
154
+
155
+ nullValue() { store(null); },
156
+ booleanValue(b) { store(!!b); },
157
+ intValue(v) { store(Math.trunc(v)); },
158
+ float64Value(v) { store(+v); },
159
+ numericTokenValue(s) { store(+s); },
160
+ stringValue(s) { store(`${s}`); },
161
+
162
+ parseErrorReceiver: null,
163
+ }
164
+ jsonAdapter.encodeToJson(value, jsonProducer);
165
+ return stack[0][0];
166
+ };
167
+
168
+ /** @type {{}} */
169
+ let emptySingleton = Object.freeze(
170
+ // Prototype for empty
171
+ Object.create(
172
+ Object.freeze(
173
+ Object.create(
174
+ null,
175
+ {
176
+ toString: {
177
+ value: function toString() { return "(empty)" }
178
+ }
179
+ }
180
+ )
181
+ )
182
+ )
183
+ );
184
+
185
+ /** @return {{}} */
186
+ export function empty() { return emptySingleton }
package/date.js CHANGED
File without changes
package/deque.js CHANGED
File without changes
package/float.js CHANGED
File without changes
package/index.js CHANGED
@@ -8,6 +8,7 @@ export * from "./float.js";
8
8
  export * from "./interface.js";
9
9
  export * from "./listed.js";
10
10
  export * from "./mapped.js";
11
+ export * from "./net.js";
11
12
  export * from "./pair.js";
12
13
  export * from "./regex.js";
13
14
  export * from "./string.js";
package/interface.js CHANGED
@@ -37,7 +37,7 @@ export const type = (...superTypes) => {
37
37
 
38
38
  class Union {
39
39
  static [Symbol.hasInstance] = (instance) => {
40
- return key in instance;
40
+ return typeof instance === 'object' && instance !== null && key in instance;
41
41
  };
42
42
  }
43
43
 
package/listed.js CHANGED
File without changes
package/mapped.js CHANGED
@@ -156,7 +156,7 @@ export const mappedHas = (map, key) => {
156
156
  * @returns {Readonly<K[]>}
157
157
  */
158
158
  export const mappedKeys = (map) => {
159
- return Object.freeze(Array.prototype.slice.call(map.keys()));
159
+ return Object.freeze(Array.from(map.keys()));
160
160
  }
161
161
 
162
162
  /**
@@ -165,7 +165,7 @@ export const mappedKeys = (map) => {
165
165
  * @returns {Readonly<V[]>}
166
166
  */
167
167
  export const mappedValues = (map) => {
168
- return Object.freeze(Array.prototype.slice.call(map.values()));
168
+ return Object.freeze(Array.from(map.values()));
169
169
  }
170
170
 
171
171
  /**
package/net.js ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @param {string} url
3
+ * @param {"GET" | "POST"} method
4
+ * @param {string | null} bodyContent
5
+ * @param {string | null} bodyMimeType
6
+ * @return {Promise<Response>}
7
+ */
8
+ export function stdNetSend(url, method, bodyContent, bodyMimeType) {
9
+ let details = { method };
10
+ if (typeof bodyContent === 'string') {
11
+ details.body = bodyContent;
12
+ if (typeof bodyMimeType === 'string') {
13
+ details.headers = { 'Content-Type': bodyMimeType };
14
+ }
15
+ }
16
+ return fetch(url, details);
17
+ }
18
+
19
+ /**
20
+ * @param {Response} r
21
+ * @return {number} an HTTP status code
22
+ */
23
+ export function netResponseGetStatus(r) {
24
+ return r.status;
25
+ }
26
+
27
+ /**
28
+ * @param {Response} r
29
+ * @return {string | null} the mime-type of the body.
30
+ */
31
+ export function netResponseGetContentType(r) {
32
+ return r.headers.get('Content-Type') || null;
33
+ }
34
+
35
+ /**
36
+ * @param {Response} r
37
+ * @return {Promise<string | null>} the body content.
38
+ */
39
+ export function netResponseGetBodyContent(r) {
40
+ return r.text();
41
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@temperlang/core",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Runtime support for JS generated by Temper",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/pair.js CHANGED
File without changes
package/regex.js CHANGED
@@ -108,7 +108,7 @@ export const regexCompiledSplit = (_, compiled, text) => {
108
108
  };
109
109
 
110
110
  /**
111
- * @param {RegExp} _
111
+ * @param {unknown} _
112
112
  * @param {string} formatted
113
113
  * @returns {RegExp}
114
114
  */
@@ -139,10 +139,16 @@ export const regexFormatterAdjustCodeSet = (self, codeSet, regexRefs) => {
139
139
  return codeSet;
140
140
  };
141
141
 
142
+ /**
143
+ * @param {unknown} _
144
+ * @param {[string]} out
145
+ * @param {number} code
146
+ * @param {boolean} insideCodeSet
147
+ */
142
148
  export const regexFormatterPushCodeTo = (_, out, code, insideCodeSet) => {
143
149
  // Ignore insideCodeSet for now.
144
150
  // TODO(tjp, regex): Get fancier, including with work in Temper.
145
- out.push(`\\u{${code.toString(16)}}`);
151
+ out[0] += `\\u{${code.toString(16)}}`;
146
152
  };
147
153
 
148
154
  // Cached later for some approximate efficiency.
package/string.js CHANGED
@@ -1,12 +1,25 @@
1
1
  import { requireIsSafeInteger } from "./check-type.js";
2
2
  import {bubble} from "./core.js";
3
3
 
4
+ /**
5
+ * Implements extension method String::fromCodePoint
6
+ * @param {number} codePoint
7
+ * @returns {string}
8
+ */
9
+ export const stringFromCodePoint = (codePoint) => {
10
+ denySurrogate(codePoint);
11
+ return String.fromCodePoint(codePoint);
12
+ };
13
+
4
14
  /**
5
15
  * Implements extension method String::fromCodePoints
6
16
  * @param {number[]} codePoints
7
17
  * @returns {string}
8
18
  */
9
19
  export const stringFromCodePoints = (codePoints) => {
20
+ for (const codePoint of codePoints) {
21
+ denySurrogate(codePoint);
22
+ }
10
23
  // TODO Append in batches if codePoints is long?
11
24
  return String.fromCodePoint(...codePoints);
12
25
  };
@@ -194,5 +207,15 @@ export const requireNoStringIndex = (i) => {
194
207
  * @param {number} c
195
208
  */
196
209
  export const stringBuilderAppendCodePoint = (s, c) => {
210
+ denySurrogate(c);
197
211
  s[0] += String.fromCodePoint(c);
198
212
  }
213
+
214
+ /**
215
+ * @param {number} c
216
+ */
217
+ const denySurrogate = (c) => {
218
+ if (c >= 0xD800 && c <= 0xDFFF) {
219
+ throw new RangeError(`Invalid Unicode scalar value ${c}`)
220
+ }
221
+ }