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

[Package Importer] Embedded Host #260

Merged
merged 31 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
32e455f
Export nodePackageImporter
jamesnw Oct 26, 2023
8de2e60
Setup NodePackageImporter message
jamesnw Oct 27, 2023
67c812d
Add nodePackageImporter to legacy importers
jamesnw Oct 30, 2023
7bda416
Fix typo
jamesnw Nov 1, 2023
7b82352
Update protocol version
jamesnw Nov 9, 2023
e566b2f
Change export to Symbol
jamesnw Nov 17, 2023
e591fad
Remove type predicate, move check inline
jamesnw Nov 17, 2023
317ab80
Workaround symbol changes
jamesnw Nov 21, 2023
8c95697
Add link to Typescript issue
jamesnw Nov 22, 2023
5a5cfd2
Adjust entrypoint logic
jamesnw Nov 27, 2023
b3f5414
Address review
jamesnw Dec 4, 2023
cf4b0cc
Lint
jamesnw Dec 4, 2023
97b3685
review
jgerigmeyer Dec 15, 2023
34298c4
Workaround Node regression: https://github.com/nodejs/node/issues/51167
jgerigmeyer Dec 15, 2023
2417f0b
Merge branch 'main' into feature.package-importer
jgerigmeyer Dec 15, 2023
b5c84a6
Update NodePackageImporter to class
jamesnw Dec 19, 2023
8964f75
Revert legacyImporterProtocol
jamesnw Dec 20, 2023
a55acff
Fix path import, legacy importer options.
jamesnw Dec 20, 2023
a469cf1
Merge branch 'main' into feature.package-importer
jgerigmeyer Jan 5, 2024
0f7f3f9
remove outdated legacy importer syntax
jgerigmeyer Jan 5, 2024
75e338a
re-add legacy pkgImporter logic
jgerigmeyer Jan 5, 2024
b8e96d6
Address review
jgerigmeyer Jan 7, 2024
623a0b9
Merge branch 'main' of https://github.com/sass/embedded-host-node int…
jamesnw Jan 17, 2024
988fabb
Update protocol version
jamesnw Jan 17, 2024
abd2a71
Merge branch 'main' of https://github.com/sass/embedded-host-node int…
jamesnw Jan 18, 2024
f05aa50
Address review
jgerigmeyer Jan 25, 2024
83be63a
Update entry point to directory
jamesnw Feb 1, 2024
be27f0b
Use directory of require.main.filename
jamesnw Feb 1, 2024
dfe637a
Remove redundant cwd in p.resolve
jamesnw Feb 1, 2024
1f4489c
Make entryPointDirectoryKey readonly and non-nullable
jgerigmeyer Feb 2, 2024
f571bfe
typo
jgerigmeyer Feb 2, 2024
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
5 changes: 5 additions & 0 deletions lib/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const compile = sass.compile;
export const compileAsync = sass.compileAsync;
export const compileString = sass.compileString;
export const compileStringAsync = sass.compileStringAsync;
export const nodePackageImporter = sass.nodePackageImporter;
export const Logger = sass.Logger;
export const CalculationInterpolation = sass.CalculationInterpolation
export const CalculationOperation = sass.CalculationOperation
Expand Down Expand Up @@ -60,6 +61,10 @@ export default {
defaultExportDeprecation();
return sass.compileStringAsync;
},
get nodePackageImporter() {
defaultExportDeprecation();
return sass.nodePackageImporter;
},
get Logger() {
defaultExportDeprecation();
return sass.Logger;
Expand Down
1 change: 1 addition & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export {
compileString,
compileAsync,
compileStringAsync,
nodePackageImporter,
} from './src/compile';
export {render, renderSync} from './src/legacy';

Expand Down
2 changes: 2 additions & 0 deletions lib/src/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
legacyImporterProtocol,
} from './legacy/utils';

export {nodePackageImporter} from './importer-registry';

/// Allow the legacy API to pass in an option signaling to the modern API that
/// it's being run in legacy mode.
///
Expand Down
40 changes: 37 additions & 3 deletions lib/src/importer-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,19 @@ import {URL} from 'url';
import {inspect} from 'util';

import * as utils from './utils';
import {FileImporter, Importer, Options} from './vendor/sass';
import {
FileImporter,
Importer,
NodePackageImporter,
Options,
} from './vendor/sass';
import * as proto from './vendor/embedded_sass_pb';
import {catchOr, thenOr, PromiseOr} from './utils';

export const nodePackageImporter: NodePackageImporter = {
_NodePackageImporterBrand: '',
jamesnw marked this conversation as resolved.
Show resolved Hide resolved
};

/**
* A registry of importers defined in the host that can be invoked by the
* compiler.
Expand Down Expand Up @@ -41,12 +50,37 @@ export class ImporterRegistry<sync extends 'sync' | 'async'> {
);
}

// Type predicate for NodePackageImporter
isNodePackageImporter(
importer: Importer<sync> | FileImporter<sync> | NodePackageImporter
): importer is NodePackageImporter {
return (
(importer as NodePackageImporter)._NodePackageImporterBrand !== undefined
);
}

/** Converts an importer to a proto without adding it to `this.importers`. */
register(
importer: Importer<sync> | FileImporter<sync>
importer: Importer<sync> | FileImporter<sync> | NodePackageImporter
): proto.InboundMessage_CompileRequest_Importer {
const message = new proto.InboundMessage_CompileRequest_Importer();
if ('canonicalize' in importer) {
if (this.isNodePackageImporter(importer)) {
if (importer !== nodePackageImporter) {
throw 'Incorrect Node Package Importer used';
jgerigmeyer marked this conversation as resolved.
Show resolved Hide resolved
}
const importerMessage = new proto.NodePackageImporter();
const entryPointURL = require.main?.filename;
if (!entryPointURL) {
throw new Error(
'Node Package Importer requires access to a filesystem.'
jgerigmeyer marked this conversation as resolved.
Show resolved Hide resolved
);
}
importerMessage.entryPointUrl = entryPointURL;
message.importer = {
case: 'nodePackageImporter',
value: importerMessage,
};
} else if ('canonicalize' in importer) {
if ('findFileUrl' in importer) {
throw new Error(
'Importer may not contain both canonicalize() and findFileUrl(): ' +
Expand Down
44 changes: 30 additions & 14 deletions lib/src/legacy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import * as fs from 'fs';
import * as p from 'path';
import {pathToFileURL, URL} from 'url';
import {nodePackageImporter} from '../importer-registry';

import {Exception} from '../exception';
import {
Expand All @@ -31,6 +32,8 @@ import {
LegacyStringOptions,
Options,
StringOptions,
Importer,
FileImporter,
} from '../vendor/sass';
import {wrapFunction} from './value/wrap';
import {endOfLoadProtocol, LegacyImporterWrapper} from './importer';
Expand Down Expand Up @@ -140,21 +143,28 @@ function convertOptions<sync extends 'sync' | 'async'>(
functions[signature.trimLeft()] = wrapFunction(self, callback, sync);
}

const importers =
let importers;
if (
options.importer &&
(!(options.importer instanceof Array) || options.importer.length > 0)
? [
new LegacyImporterWrapper(
self,
options.importer instanceof Array
? options.importer
: [options.importer],
options.includePaths ?? [],
options.file ?? 'stdin',
sync
),
]
: undefined;
) {
importers = [
new LegacyImporterWrapper(
self,
options.importer instanceof Array
? options.importer
: [options.importer],
options.includePaths ?? [],
options.file ?? 'stdin',
sync
),
];
}
if (options.pkgImporter === 'node') {
importers = importers
? [nodePackageImporter, ...importers]
: [nodePackageImporter];
}

return {
functions,
Expand All @@ -178,14 +188,20 @@ function convertStringOptions<sync extends 'sync' | 'async'>(
): StringOptions<sync> & {legacy: true} {
const modernOptions = convertOptions(options, sync);

// Find the first non-nodePackageImporter to pass as legacy `importer` option.
// nodePackageImporter will be passed in `modrenOptions.importers`.
const importer = modernOptions.importers?.find(
_importer => _importer !== nodePackageImporter
) as Importer<sync> | FileImporter<sync>;

return {
...modernOptions,
url: options.file
? options.importer
? pathToLegacyFileUrl(options.file)
: pathToFileURL(options.file)
: new URL(legacyImporterProtocol),
importer: modernOptions.importers ? modernOptions.importers[0] : undefined,
importer,
syntax: options.indentedSyntax ? 'indented' : 'scss',
};
}
Expand Down
Loading