Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions src/js/builtins/ConsoleObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,11 @@ export function write(this: Console, input) {
// TODO: probably could extract `getStringWidth`; probably make that a native function. note how it is copied from `readline.js`
export function createConsoleConstructor(console: typeof globalThis.console) {
const { inspect, formatWithOptions } = require("node:util");
const { isBuffer } = require("node:buffer");
const {
Buffer: { isBuffer },
} = require("node:buffer");
const { isMapIterator, isSetIterator } = require("node:util/types");
const { previewEntries } = require("internal/util/inspect");

const { validateObject, validateInteger, validateArray, validateOneOf } = require("internal/validators");
const kMaxGroupIndentation = 1000;
Expand Down Expand Up @@ -191,11 +194,8 @@ export function createConsoleConstructor(console: typeof globalThis.console) {
for (let i = 0; i < row.length; i++) {
const cell = row[i];
const len = getStringWidth(cell);
const needed = (columnWidths[i] - len) / 2;
// round(needed) + ceil(needed) will always add up to the amount
// of spaces we need while also left justifying the output.
out +=
(StringPrototypeRepeat as any).$call(" ", needed) + cell + StringPrototypeRepeat.$call(" ", Math.ceil(needed));
const needed = columnWidths[i] - len;
out += cell + StringPrototypeRepeat.$call(" ", Math.ceil(needed));
if (i !== row.length - 1) out += tableChars.middle;
}
out += tableChars.right;
Expand Down Expand Up @@ -666,11 +666,11 @@ export function createConsoleConstructor(console: typeof globalThis.console) {
const mapIter = isMapIterator(tabularData);
let isKeyValue = false;
let i = 0;
// if (mapIter) {
// const res = previewEntries(tabularData, true);
// tabularData = res[0];
// isKeyValue = res[1];
// }
if (mapIter) {
const res = previewEntries(tabularData, true);
tabularData = res[0];
isKeyValue = res[1];
}

if (isKeyValue || $isMap(tabularData)) {
const keys = [];
Expand All @@ -693,7 +693,9 @@ export function createConsoleConstructor(console: typeof globalThis.console) {
}

const setIter = isSetIterator(tabularData);
// if (setIter) tabularData = previewEntries(tabularData);
// Node passes only the iterator; V8's previewEntries infers it. Bun's
// helper needs the flag, and returns [entries, isKeyValue].
if (setIter) tabularData = previewEntries(tabularData, true)[0];

const setlike = setIter || mapIter || $isSet(tabularData);
if (setlike) {
Expand Down
1 change: 1 addition & 0 deletions src/js/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -2745,6 +2745,7 @@ export default {
formatWithOptions,
stripVTControlCharacters,
getStringWidth,
previewEntries,
//! non-standard properties, should these be kept? (not currently exposed)
//stylizeWithColor,
//stylizeWithHTML(str, styleType) {
Expand Down
16 changes: 8 additions & 8 deletions test/js/node/console/console-table-iterators.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ test("console.Console#table renders Map and Set iterators", async () => {
expect(stderr).toBe("");
}
expect(stdout).toMatchInlineSnapshot(`
"┌───────────────────┬────────────┐
│ (iteration index) │ Values
├───────────────────┼────────────┤
0[ 'a', 1 ]
1[ 'b', 2 ]
└───────────────────┴────────────┘
"┌───────────────────┬─────┬────────┐
│ (iteration index) │ Key │ Values │
├───────────────────┼─────┼────────┤
0 │ 'a' │ 1
1 │ 'b' │ 2
└───────────────────┴─────┴────────┘
┌───────────────────┬────────┐
│ (iteration index) │ Values │
├───────────────────┼────────┤
0 7
1 8
07
18
└───────────────────┴────────┘
"
`);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use strict';

// This tests NODE_COMPILE_CACHE works in existing directory.

require('../common');
const { spawnSyncAndAssert } = require('../common/child_process');
const assert = require('assert');
const tmpdir = require('../common/tmpdir');
const fixtures = require('../common/fixtures');
const fs = require('fs');

function testAllowed(readDir, writeDir, envDir) {
console.log(readDir, writeDir, envDir); // Logging for debugging.

tmpdir.refresh();
const dummyDir = tmpdir.resolve('dummy');
fs.mkdirSync(dummyDir);
const script = tmpdir.resolve(dummyDir, 'empty.js');
fs.copyFileSync(fixtures.path('empty.js'), script);
// If the directory doesn't exist, permission will just be disallowed.
fs.mkdirSync(tmpdir.resolve(envDir));

spawnSyncAndAssert(
process.execPath,
[
'--permission',
`--allow-fs-read=${dummyDir}`,
`--allow-fs-read=${readDir}`,
`--allow-fs-write=${writeDir}`,
script,
],
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
NODE_COMPILE_CACHE: `${envDir}`
},
cwd: tmpdir.path
},
{
stderr(output) {
assert.match(output, /writing cache for .*empty\.js.*success/);
return true;
}
});

spawnSyncAndAssert(
process.execPath,
[
'--permission',
`--allow-fs-read=${dummyDir}`,
`--allow-fs-read=${readDir}`,
`--allow-fs-write=${writeDir}`,
script,
],
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
NODE_COMPILE_CACHE: `${envDir}`
},
cwd: tmpdir.path
},
{
stderr(output) {
assert.match(output, /cache for .*empty\.js was accepted/);
return true;
}
});
}

{
testAllowed(tmpdir.resolve('.compile_cache'), tmpdir.resolve('.compile_cache'), '.compile_cache');
testAllowed(tmpdir.resolve('.compile_cache'), tmpdir.resolve('.compile_cache'), tmpdir.resolve('.compile_cache'));
testAllowed('*', '*', '.compile_cache');
testAllowed('*', tmpdir.resolve('.compile_cache'), '.compile_cache');
testAllowed(tmpdir.resolve('.compile_cache'), '*', '.compile_cache');
}
169 changes: 169 additions & 0 deletions test/js/node/test/parallel/test-compile-cache-typescript-commonjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
'use strict';

// This tests NODE_COMPILE_CACHE works for CommonJS with types.

const common = require('../common');
if (!process.config.variables.node_use_amaro) {
common.skip('Requires Amaro');
}
const { spawnSyncAndAssert } = require('../common/child_process');
const assert = require('assert');
const tmpdir = require('../common/tmpdir');
const fixtures = require('../common/fixtures');

// Check cache for .ts files that would be run as CommonJS.
{
tmpdir.refresh();
const dir = tmpdir.resolve('.compile_cache_dir');
const script = fixtures.path('typescript', 'ts', 'test-commonjs-parsing.ts');

spawnSyncAndAssert(
process.execPath,
[script],
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
NODE_COMPILE_CACHE: dir
},
cwd: tmpdir.path
},
{
stderr(output) {
assert.match(output, /saving transpilation cache for StrippedTypeScript .*test-commonjs-parsing\.ts/);
assert.match(output, /writing cache for StrippedTypeScript .*test-commonjs-parsing\.ts.*success/);
assert.match(output, /writing cache for CommonJS .*test-commonjs-parsing\.ts.*success/);
return true;
}
});

spawnSyncAndAssert(
process.execPath,
[script],
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
NODE_COMPILE_CACHE: dir
},
cwd: tmpdir.path
},
{
stderr(output) {
assert.match(output, /retrieving transpile cache for StrippedTypeScript .*test-commonjs-parsing\.ts.*success/);
assert.match(output, /reading cache from .* for CommonJS .*test-commonjs-parsing\.ts.*success/);
assert.match(output, /skip persisting StrippedTypeScript .*test-commonjs-parsing\.ts because cache was the same/);
assert.match(output, /V8 code cache for CommonJS .*test-commonjs-parsing\.ts was accepted, keeping the in-memory entry/);
assert.match(output, /skip persisting CommonJS .*test-commonjs-parsing\.ts because cache was the same/);
return true;
}
});
}

// Check cache for .cts files that require .cts files.
{
tmpdir.refresh();
const dir = tmpdir.resolve('.compile_cache_dir');
const script = fixtures.path('typescript', 'cts', 'test-require-commonjs.cts');

spawnSyncAndAssert(
process.execPath,
[script],
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
NODE_COMPILE_CACHE: dir
},
cwd: tmpdir.path
},
{
stderr(output) {
assert.match(output, /writing cache for StrippedTypeScript .*test-require-commonjs\.cts.*success/);
assert.match(output, /writing cache for StrippedTypeScript .*test-cts-export-foo\.cts.*success/);
assert.match(output, /writing cache for CommonJS .*test-require-commonjs\.cts.*success/);
assert.match(output, /writing cache for CommonJS .*test-cts-export-foo\.cts.*success/);
return true;
}
});

spawnSyncAndAssert(
process.execPath,
[script],
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
NODE_COMPILE_CACHE: dir
},
cwd: tmpdir.path
},
{
stderr(output) {
assert.match(output, /retrieving transpile cache for StrippedTypeScript .*test-require-commonjs\.cts.*success/);
assert.match(output, /skip persisting StrippedTypeScript .*test-require-commonjs\.cts because cache was the same/);
assert.match(output, /retrieving transpile cache for StrippedTypeScript .*test-cts-export-foo\.cts.*success/);
assert.match(output, /skip persisting StrippedTypeScript .*test-cts-export-foo\.cts because cache was the same/);

assert.match(output, /V8 code cache for CommonJS .*test-require-commonjs\.cts was accepted, keeping the in-memory entry/);
assert.match(output, /skip persisting CommonJS .*test-require-commonjs\.cts because cache was the same/);
assert.match(output, /V8 code cache for CommonJS .*test-cts-export-foo\.cts was accepted, keeping the in-memory entry/);
assert.match(output, /skip persisting CommonJS .*test-cts-export-foo\.cts because cache was the same/);
return true;
}
});
}

// Check cache for .cts files that require .mts files.
{
tmpdir.refresh();
const dir = tmpdir.resolve('.compile_cache_dir');
const script = fixtures.path('typescript', 'cts', 'test-require-mts-module.cts');

spawnSyncAndAssert(
process.execPath,
[script],
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
NODE_COMPILE_CACHE: dir
},
cwd: tmpdir.path
},
{
stderr(output) {
assert.match(output, /writing cache for StrippedTypeScript .*test-require-mts-module\.cts.*success/);
assert.match(output, /writing cache for StrippedTypeScript .*test-mts-export-foo\.mts.*success/);
assert.match(output, /writing cache for CommonJS .*test-require-mts-module\.cts.*success/);
assert.match(output, /writing cache for ESM .*test-mts-export-foo\.mts.*success/);
return true;
}
});

spawnSyncAndAssert(
process.execPath,
[script],
{
env: {
...process.env,
NODE_DEBUG_NATIVE: 'COMPILE_CACHE',
NODE_COMPILE_CACHE: dir
},
cwd: tmpdir.path
},
{
stderr(output) {
assert.match(output, /retrieving transpile cache for StrippedTypeScript .*test-require-mts-module\.cts.*success/);
assert.match(output, /skip persisting StrippedTypeScript .*test-require-mts-module\.cts because cache was the same/);
assert.match(output, /retrieving transpile cache for StrippedTypeScript .*test-mts-export-foo\.mts.*success/);
assert.match(output, /skip persisting StrippedTypeScript .*test-mts-export-foo\.mts because cache was the same/);

assert.match(output, /V8 code cache for CommonJS .*test-require-mts-module\.cts was accepted, keeping the in-memory entry/);
assert.match(output, /skip persisting CommonJS .*test-require-mts-module\.cts because cache was the same/);
assert.match(output, /V8 code cache for ESM .*test-mts-export-foo\.mts was accepted, keeping the in-memory entry/);
assert.match(output, /skip persisting ESM .*test-mts-export-foo\.mts because cache was the same/);
return true;
}
});
}
Loading
Loading