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

Prettier 3 #2251

Merged
merged 7 commits into from
Dec 23, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
135 changes: 135 additions & 0 deletions .yarn/patches/sync-threads-npm-1.0.1-54233b9086.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
diff --git a/src/index.js b/src/index.js
index 8bfd9901a4eb1c6771af93c0d9723fff97b49c1e..635894b555042cf1a063bc7f5b0bae2953967da2 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,27 +1,55 @@
// @ts-check

const v8 = require('v8')
-const { Worker, workerData } = require('worker_threads')
+const { Worker, parentPort } = require('worker_threads')

const INT32_BYTES = 4

exports.createSyncFn = createSyncFn
exports.runAsWorker = runAsWorker

+/**
+ * @param {string} filename
+ * @returns {Worker}
+ */
+function initWorker(filename) {
+ const worker = new Worker(filename)
+
+ worker.on('error', (e) => {
+ throw e
+ })
+
+ // Make sure it won't block the process from exiting
+ worker.unref()
+
+ return worker
+}
+
/**
* @param {string} filename
* @param {number} bufferSize
- * @returns (inputData?: any) => any
+ * @param {number} timeoutMs Timeout in Milliseconds
+ * @returns {(...args: any) => any}
*/
-function createSyncFn(filename, bufferSize = 64 * 1024) {
- const sharedBuffer = new SharedArrayBuffer(bufferSize)
- const semaphore = new Int32Array(sharedBuffer)
- return (inputData = {}) => {
- const worker = new Worker(filename, { workerData: { inputData, sharedBuffer } })
- worker.on('error', (e) => {
- throw e
- })
- Atomics.wait(semaphore, 0, 0)
+function createSyncFn(filename, bufferSize = 64 * 1024, timeoutMs) {
+ let worker = initWorker(filename)
+
+ return (...inputData) => {
+ const sharedBuffer = new SharedArrayBuffer(bufferSize)
+ const semaphore = new Int32Array(sharedBuffer)
+
+ worker.postMessage({ inputData, sharedBuffer })
+
+ const result = Atomics.wait(semaphore, 0, 0, timeoutMs)
+ if (result === 'timed-out') {
+ // If the call timed out, we terminate the current worker
+ // This avoid leaving resources stuck or penalize the next function call
+ worker.terminate()
+ worker = initWorker(filename)
+
+ throw new Error('Timed out running async function')
+ }
+
let length = semaphore[0]
let didThrow = false
if (length < 0) {
@@ -30,27 +58,52 @@ function createSyncFn(filename, bufferSize = 64 * 1024) {
}
const data = v8.deserialize(Buffer.from(sharedBuffer, INT32_BYTES, length))
if (didThrow) {
- throw data
+ throw Object.assign(data.error, data.properties)
}
return data
}
}

/**
- * @param {(inputData: any) => Promise<any>} workerAsyncFn
+ * Serialization does not copy properties of error objects
+ * @param {Record<string, any> | unknown} object
+ * @returns {Record<string, any> | undefined}
+ */
+function extractProperties(object) {
+ if (object && typeof object === 'object') {
+ /** @type {Record<string, any>} */
+ const knownObj = object
+ /** @type {Record<string, any>} */
+ const properties = {}
+ for (const key in object) {
+ properties[key] = knownObj[key]
+ }
+ return properties
+ }
+}
+
+/**
+ * @param {(...inputData: any) => Promise<any>} workerAsyncFn
* @returns void
*/
async function runAsWorker(workerAsyncFn) {
- const { inputData, sharedBuffer } = workerData
- let data,
- didThrow = false
- try {
- data = await workerAsyncFn(inputData)
- } catch (e) {
- data = e
- didThrow = true
+ if (!parentPort) {
+ throw new Error('Cannot connect to parent thread, are you running this function in a worker ?')
}
- notifyParent(sharedBuffer, data, didThrow)
+
+ parentPort.on('message', ({ inputData, sharedBuffer }) => {
+ ;(async () => {
+ let data,
+ didThrow = false
+ try {
+ data = await workerAsyncFn(...inputData)
+ } catch (error) {
+ data = { error, properties: extractProperties(error) }
+ didThrow = true
+ }
+ notifyParent(sharedBuffer, data, didThrow)
+ })()
+ })
}

/**
28 changes: 22 additions & 6 deletions packages/crafty-commons-swc/src/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,22 @@ function extendConfiguration(crafty, bundle, swcOptions) {
debug("SWC configuration", swcOptions);
}

function getConfigurationBase(crafty, bundle, hasHelperDependency) {
function getConfigurationBase(
crafty,
bundle,
hasHelperDependency,
syntax = "ecmascript"
) {
const swcOptions = {
jsc: {
parser: {
syntax,
jsx: true,
decorators: true
decorators: true,
usingDecl: true
},
experimental: {
keepImportAssertions: true
}
},
env: {
Expand All @@ -57,8 +67,13 @@ function getConfiguration(crafty, bundle, hasHelperDependency) {
return options;
}

function getConfigurationWebpack(crafty, bundle, hasHelperDependency) {
const options = getConfigurationBase(crafty, bundle, hasHelperDependency);
function getConfigurationWebpack(crafty, bundle, hasHelperDependency, syntax) {
const options = getConfigurationBase(
crafty,
bundle,
hasHelperDependency,
syntax
);

// Always enabled
options.jsc.externalHelpers = true;
Expand All @@ -77,11 +92,12 @@ function getConfigurationWebpack(crafty, bundle, hasHelperDependency) {
return options;
}

function getConfigurationGulp(crafty, bundle) {
function getConfigurationGulp(crafty, bundle, syntax) {
const options = getConfigurationBase(
crafty,
bundle,
hasSwcHelpersDependency()
hasSwcHelpersDependency(),
syntax
);

if (crafty.getEnvironment() === "production") {
Expand Down
2 changes: 1 addition & 1 deletion packages/crafty-preset-typescript/src/gulp.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ module.exports = function createTask(crafty, bundle, gulp) {
const {
getConfigurationGulp
} = require("@swissquote/crafty-commons-swc/src/configuration.js");
const swcOptions = getConfigurationGulp(crafty, bundle);
const swcOptions = getConfigurationGulp(crafty, bundle, "typescript");
jsStream = jsStream.pipe(swc(swcOptions));

if (bundle.concat) {
Expand Down
9 changes: 8 additions & 1 deletion packages/crafty-preset-typescript/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,14 @@ module.exports = {
.loader(
require.resolve("@swissquote/crafty-commons-swc/packages/swc-loader.js")
)
.options(getConfigurationWebpack(crafty, bundle, hasHelperDependency));
.options(
getConfigurationWebpack(
crafty,
bundle,
hasHelperDependency,
"typescript"
)
);

const tsOptions = {
// https://webpack.js.org/guides/build-performance/#typescript-loader
Expand Down
12 changes: 9 additions & 3 deletions packages/eslint-plugin-swissquote/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ This plugin comes with four presets

- `eslint-plugin-prettier` Uses Prettier to format your code.

Due to breaking changes in behavior from Prettier 1 to Prettier 2 without configuration options to revert to Prettier 1's behavior, this preset provides both Prettier 1 and Prettier 2.
By default we ship with Prettier 1 for backwards compatibility.
Due to breaking changes in behavior between Prettier major versions, this preset provides multiple Prettier versions.
By default we use Prettier 1 for backwards compatibility.

You can choose which version you want to use by using ESLint's `settings` key.
Valid values are `prettier:1` and `prettier:2`.
Valid values are `prettier:1`, `prettier:2`, and `prettier:3`.

```javascript
{
Expand All @@ -36,6 +36,12 @@ Valid values are `prettier:1` and `prettier:2`.
}
```

| Prettier Version | TypeScript Compatibility |
| ---------------- | ------------------------ |
| Prettier 1 | >= 1 && <=4.2 |
| Prettier 2 | >= 1 && <=5.1 |
| Prettier 3 | >= 1 |

### Plugins in the `recommended` preset

- `eslint-plugin-import` provides some rules to clean imports.
Expand Down
22 changes: 21 additions & 1 deletion packages/eslint-plugin-swissquote/build.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const fs = require("fs");
const path = require("path");
const { getExternals } = require("../../utils/externals");

const externals = getExternals();
Expand All @@ -16,6 +17,7 @@ module.exports = [

fs.copyFileSync(src, "dist/eslint-plugin-react-hooks/index.js");
},
builder => builder("sync-threads").package(),
builder => builder("estraverse").package(),
builder => builder("function-bind").package(),
builder =>
Expand Down Expand Up @@ -208,9 +210,27 @@ module.exports = [
}),

// Prettier specific stuff
() => {
console.log("Copy prettier 3");
const src = path.dirname(require.resolve("prettier/package.json"));

fs.mkdirSync("dist/prettier/plugins", { recursive: true });

// We only copy the plugins we need
const files = [
"index.mjs",
"doc.mjs",
"plugins/typescript.mjs",
"plugins/babel.mjs",
"plugins/estree.mjs"
];

for (const file of files) {
fs.copyFileSync(path.join(src, file), path.join("dist/prettier", file));
}
},
builder =>
builder("prettier")
builder("prettier2")
.package()
.externals({
// Provided by this package
Expand Down
6 changes: 4 additions & 2 deletions packages/eslint-plugin-swissquote/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@
"eslint-plugin-i": "2.29.1",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "4.6.0",
"prettier": "2.8.8",
"prettier": "3.1.1",
"prettier-linter-helpers": "1.0.0",
"prettier1": "npm:prettier@1.19.1"
"prettier1": "npm:prettier@1.19.1",
"prettier2": "npm:prettier@2.8.8",
"sync-threads": "patch:sync-threads@npm%3A1.0.1#~/.yarn/patches/sync-threads-npm-1.0.1-54233b9086.patch"
},
"engines": {
"node": ">=18"
Expand Down
20 changes: 20 additions & 0 deletions packages/eslint-plugin-swissquote/packages/prettier1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const prettier = require("../dist/prettier1/index.js");

module.exports = {
/**
* @param {string} path
* @param {any} config
* @returns {Promise<{ ignored: boolean, inferredParser: string }>}
*/
getFileInfo(path, config) {
return prettier.getFileInfo.sync(path, config);
},
/**
* @param {string} source
* @param {any} options
* @returns {Promise<string>}
*/
format(source, options) {
return prettier.format(source, options);
}
}
20 changes: 20 additions & 0 deletions packages/eslint-plugin-swissquote/packages/prettier2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const prettier = require("../dist/prettier2/index.js");

module.exports = {
/**
* @param {string} path
* @param {any} config
* @returns {Promise<{ ignored: boolean, inferredParser: string }>}
*/
getFileInfo(path, config) {
return prettier.getFileInfo.sync(path, config);
},
/**
* @param {string} source
* @param {any} options
* @returns {Promise<string>}
*/
format(source, options) {
return prettier.format(source, options);
}
}
20 changes: 20 additions & 0 deletions packages/eslint-plugin-swissquote/packages/prettier3.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getFileInfo, format } from "../dist/prettier/index.mjs";

export default {
/**
* @param {string} path
* @param {any} config
* @returns {Promise<{ ignored: boolean, inferredParser: string }>}
*/
getFileInfo(path, config) {
return getFileInfo(path, config);
},
/**
* @param {string} source
* @param {any} options
* @returns {Promise<string>}
*/
format(source, options) {
return format(source, options);
}
}
1 change: 1 addition & 0 deletions packages/eslint-plugin-swissquote/packages/sync-threads.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require("../dist/sync-threads/index.js");
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ Generated by [AVA](https://avajs.dev).
},
]

## Works with complex types

> Snapshot 1

[]

## Works with recent TypeScript features

> Snapshot 1
Expand Down
Binary file not shown.