Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

Fix echo collision bug

Closes https://github.com/gleam-lang/gleam/issues/4402

+41 -15
+5
CHANGELOG.md
··· 322 322 the pattern if it was the only expression inside a block. 323 323 ([Surya Rose](https://github.com/GearsDatapacks)) 324 324 325 + - Fixed a bug where the code generated for `echo` on JavaScript could have name 326 + collisions if there are functions called `console` or `process`, or custom type 327 + variants called `Object` or `Deno` defined in the module. 328 + ([Louis Pilfold](https://github.com/lpil)) 329 + 325 330 ## v1.9.1 - 2025-03-10 326 331 327 332 ### Formatter
+36 -15
compiler-core/templates/echo.mjs
··· 4 4 const file_line = `${file}:${line}`; 5 5 const string_value = echo$inspect(value); 6 6 7 - if (typeof process === "object" && process.stderr?.write) { 7 + if (globalThis.process?.stderr?.write) { 8 8 // If we're in Node.js, use `stderr` 9 9 const string = `${grey}${file_line}${reset_color}\n${string_value}\n`; 10 10 process.stderr.write(string); 11 - } else if (typeof Deno === "object") { 11 + } else if (globalThis.Deno) { 12 12 // If we're in Deno, use `stderr` 13 13 const string = `${grey}${file_line}${reset_color}\n${string_value}\n`; 14 - Deno.stderr.writeSync(new TextEncoder().encode(string)); 14 + globalThis.Deno.stderr.writeSync(new TextEncoder().encode(string)); 15 15 } else { 16 16 // Otherwise, use `console.log` 17 17 // The browser's console.log doesn't support ansi escape codes 18 18 const string = `${file_line}\n${string_value}`; 19 - console.log(string); 19 + globalThis.console.log(string); 20 20 } 21 21 22 22 return value; ··· 33 33 else if (char == "\\") new_str += "\\\\"; 34 34 else if (char == '"') new_str += '\\"'; 35 35 else if (char < " " || (char > "~" && char < "\u{00A0}")) { 36 - new_str += "\\u{" + char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + "}"; 36 + new_str += 37 + "\\u{" + 38 + char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + 39 + "}"; 37 40 } else { 38 41 new_str += char; 39 42 } ··· 60 63 } 61 64 62 65 function echo$inspectCustomType(record) { 63 - const props = Object.keys(record) 66 + const props = globalThis.Object.keys(record) 64 67 .map((label) => { 65 68 const value = echo$inspect(record[label]); 66 69 return isNaN(parseInt(label)) ? `${label}: ${value}` : value; 67 70 }) 68 71 .join(", "); 69 - return props ? `${record.constructor.name}(${props})` : record.constructor.name; 72 + return props 73 + ? `${record.constructor.name}(${props})` 74 + : record.constructor.name; 70 75 } 71 76 72 77 function echo$inspectObject(v) { ··· 88 93 if (v === undefined) return "Nil"; 89 94 if (t === "string") return echo$inspectString(v); 90 95 if (t === "bigint" || t === "number") return v.toString(); 91 - if (Array.isArray(v)) return `#(${v.map(echo$inspect).join(", ")})`; 92 - if (v instanceof $List) return `[${v.toArray().map(echo$inspect).join(", ")}]`; 93 - if (v instanceof $UtfCodepoint) return `//utfcodepoint(${String.fromCodePoint(v.value)})`; 96 + if (globalThis.Array.isArray(v)) 97 + return `#(${v.map(echo$inspect).join(", ")})`; 98 + if (v instanceof $List) 99 + return `[${v.toArray().map(echo$inspect).join(", ")}]`; 100 + if (v instanceof $UtfCodepoint) 101 + return `//utfcodepoint(${String.fromCodePoint(v.value)})`; 94 102 if (v instanceof $BitArray) return echo$inspectBitArray(v); 95 103 if (v instanceof $CustomType) return echo$inspectCustomType(v); 96 104 if (echo$isDict(v)) return echo$inspectDict(v); 97 - if (v instanceof Set) return `//js(Set(${[...v].map(echo$inspect).join(", ")}))`; 105 + if (v instanceof Set) 106 + return `//js(Set(${[...v].map(echo$inspect).join(", ")}))`; 98 107 if (v instanceof RegExp) return `//js(${v})`; 99 108 if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`; 100 109 if (v instanceof Function) { 101 110 const args = []; 102 - for (const i of Array(v.length).keys()) args.push(String.fromCharCode(i + 97)); 111 + for (const i of Array(v.length).keys()) 112 + args.push(String.fromCharCode(i + 97)); 103 113 return `//fn(${args.join(", ")}) { ... }`; 104 114 } 105 115 return echo$inspectObject(v); ··· 108 118 function echo$inspectBitArray(bitArray) { 109 119 // We take all the aligned bytes of the bit array starting from `bitOffset` 110 120 // up to the end of the section containing all the aligned bytes. 111 - let endOfAlignedBytes = bitArray.bitOffset + 8 * Math.trunc(bitArray.bitSize / 8); 112 - let alignedBytes = bitArraySlice(bitArray, bitArray.bitOffset, endOfAlignedBytes); 121 + let endOfAlignedBytes = 122 + bitArray.bitOffset + 8 * Math.trunc(bitArray.bitSize / 8); 123 + let alignedBytes = bitArraySlice( 124 + bitArray, 125 + bitArray.bitOffset, 126 + endOfAlignedBytes, 127 + ); 113 128 114 129 // Now we need to get the remaining unaligned bits at the end of the bit array. 115 130 // They will start after `endOfAlignedBytes` and end at `bitArray.bitSize` 116 131 let remainingUnalignedBits = bitArray.bitSize % 8; 117 132 if (remainingUnalignedBits > 0) { 118 - let remainingBits = bitArraySliceToInt(bitArray, endOfAlignedBytes, bitArray.bitSize, false, false); 133 + let remainingBits = bitArraySliceToInt( 134 + bitArray, 135 + endOfAlignedBytes, 136 + bitArray.bitSize, 137 + false, 138 + false, 139 + ); 119 140 let alignedBytesArray = Array.from(alignedBytes.rawBuffer); 120 141 let suffix = `${remainingBits}:size(${remainingUnalignedBits})`; 121 142 if (alignedBytesArray.length === 0) {