Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

module: use buffer.toString base64 #56315

Merged
merged 2 commits into from
Dec 21, 2024
Merged
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
9 changes: 9 additions & 0 deletions lib/eslint.config_partial.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ const noRestrictedSyntax = [
selector: "CallExpression[callee.object.name='assert']:not([callee.property.name='ok']):not([callee.property.name='fail']):not([callee.property.name='ifError'])",
message: 'Only use simple assertions',
},
{
// Forbids usages of `btoa` that are not caught by no-restricted-globals, like:
// ```
// const { btoa } = internalBinding('buffer');
// btoa('...');
// ```
selector: "CallExpression[callee.property.name='btoa'], CallExpression[callee.name='btoa']",
aduh95 marked this conversation as resolved.
Show resolved Hide resolved
message: "`btoa` supports only latin-1 charset, use Buffer.from(str).toString('base64') instead",
},
{
selector: 'NewExpression[callee.name=/Error$/]:not([callee.name=/^(AssertionError|NghttpError|AbortError|NodeAggregateError)$/])',
message: "Use an error exported by 'internal/errors' instead.",
Expand Down
8 changes: 5 additions & 3 deletions lib/internal/modules/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const {
} = require('internal/errors').codes;
const { getOptionValue } = require('internal/options');
const assert = require('internal/assert');
const { Buffer } = require('buffer');

/**
* The TypeScript parsing mode, either 'strip-only' or 'transform'.
Expand Down Expand Up @@ -134,9 +135,10 @@ function stripTypeScriptModuleTypes(source, filename) {
* @returns {string} The code with the source map attached.
*/
function addSourceMap(code, sourceMap) {
// TODO(@marco-ippolito) When Buffer.transcode supports utf8 to
// base64 transformation, we should change this line.
const base64SourceMap = internalBinding('buffer').btoa(sourceMap);
// The base64 encoding should be https://datatracker.ietf.org/doc/html/rfc4648#section-4,
// not base64url https://datatracker.ietf.org/doc/html/rfc4648#section-5. See data url
// spec https://tools.ietf.org/html/rfc2397#section-2.
const base64SourceMap = Buffer.from(sourceMap).toString('base64');
anonrig marked this conversation as resolved.
Show resolved Hide resolved
return `${code}\n\n//# sourceMappingURL=data:application/json;base64,${base64SourceMap}`;
}

Expand Down
65 changes: 39 additions & 26 deletions test/parallel/test-module-strip-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ common.expectWarning(
'stripTypeScriptTypes is an experimental feature and might change at any time',
);

const sourceToBeTransformed = `
namespace MathUtil {
export const add = (a: number, b: number) => a + b;
}`;
const sourceToBeTransformedMapping = 'UACY;aACK,MAAM,CAAC,GAAW,IAAc,IAAI;AACnD,GAFU,aAAA';

test('stripTypeScriptTypes', () => {
const source = 'const x: number = 1;';
const result = stripTypeScriptTypes(source);
Expand Down Expand Up @@ -48,45 +54,52 @@ test('stripTypeScriptTypes sourceUrl throws when mode is strip', () => {
});

test('stripTypeScriptTypes source map when mode is transform', () => {
const source = `
namespace MathUtil {
export const add = (a: number, b: number) => a + b;
}`;
const result = stripTypeScriptTypes(source, { mode: 'transform', sourceMap: true });
const result = stripTypeScriptTypes(sourceToBeTransformed, { mode: 'transform', sourceMap: true });
const script = new vm.Script(result);
const sourceMap =
{
version: 3,
sources: [
'<anon>',
],
sourcesContent: [
'\n namespace MathUtil {\n export const add = (a: number, b: number) => a + b;\n }',
],
sources: [''],
names: [],
mappings: ';UACY;aACK,MAAM,CAAC,GAAW,IAAc,IAAI;AACnD,GAFU,aAAA'
mappings: sourceToBeTransformedMapping,
};
assert(script.sourceMapURL, `sourceMappingURL=data:application/json;base64,${JSON.stringify(sourceMap)}`);
const inlinedSourceMap = Buffer.from(JSON.stringify(sourceMap)).toString('base64');
assert.strictEqual(script.sourceMapURL, `data:application/json;base64,${inlinedSourceMap}`);
});

test('stripTypeScriptTypes source map when mode is transform and sourceUrl', () => {
const source = `
namespace MathUtil {
export const add = (a: number, b: number) => a + b;
}`;
const result = stripTypeScriptTypes(source, { mode: 'transform', sourceMap: true, sourceUrl: 'test.ts' });
const result = stripTypeScriptTypes(sourceToBeTransformed, {
mode: 'transform',
sourceMap: true,
sourceUrl: 'test.ts'
});
const script = new vm.Script(result);
const sourceMap =
{
version: 3,
sources: ['test.ts'],
names: [],
mappings: sourceToBeTransformedMapping,
};
const inlinedSourceMap = Buffer.from(JSON.stringify(sourceMap)).toString('base64');
assert.strictEqual(script.sourceMapURL, `data:application/json;base64,${inlinedSourceMap}`);
});

test('stripTypeScriptTypes source map when mode is transform and sourceUrl with non-latin-1 chars', () => {
const sourceUrl = 'dir%20with $unusual"chars?\'åß∂ƒ©∆¬…`.cts';
const result = stripTypeScriptTypes(sourceToBeTransformed, {
mode: 'transform',
sourceMap: true,
sourceUrl,
});
const script = new vm.Script(result);
const sourceMap =
{
version: 3,
sources: [
'test.ts',
],
sourcesContent: [
'\n namespace MathUtil {\n export const add = (a: number, b: number) => a + b;\n }',
],
sources: [sourceUrl],
names: [],
mappings: ';UACY;aACK,MAAM,CAAC,GAAW,IAAc,IAAI;AACnD,GAFU,aAAA'
mappings: sourceToBeTransformedMapping,
};
assert(script.sourceMapURL, `sourceMappingURL=data:application/json;base64,${JSON.stringify(sourceMap)}`);
const inlinedSourceMap = Buffer.from(JSON.stringify(sourceMap)).toString('base64');
assert.strictEqual(script.sourceMapURL, `data:application/json;base64,${inlinedSourceMap}`);
});
Loading