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

fix: support serialization of RegExp #102

Merged
merged 3 commits into from
Apr 10, 2021
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
5 changes: 3 additions & 2 deletions src/WorkerPool.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import asyncMapSeries from 'neo-async/mapSeries';

import readBuffer from './readBuffer';
import WorkerError from './WorkerError';
import { replacer, reviver } from './serializer';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than using a custom serializer, you should use the Node serialization APIs:
https://nodejs.org/api/v8.html#v8_serialization_api

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer using a more familiar and portable API as long as it solves the same problem.

@alexander-akait what do you think about this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v8 seriliazer doesn't support many feature

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexander-akait Just run into this PR due to function option, I'm just curious what feature is missing then JSON?


const workerPath = require.resolve('./worker');

Expand Down Expand Up @@ -107,7 +108,7 @@ class PoolWorker {

writeJson(data) {
const lengthBuffer = Buffer.alloc(4);
const messageBuffer = Buffer.from(JSON.stringify(data), 'utf-8');
const messageBuffer = Buffer.from(JSON.stringify(data, replacer), 'utf-8');
lengthBuffer.writeInt32BE(messageBuffer.length, 0);
this.writePipe.write(lengthBuffer);
this.writePipe.write(messageBuffer);
Expand Down Expand Up @@ -141,7 +142,7 @@ class PoolWorker {
}
this.state = 'message read';
const messageString = messageBuffer.toString('utf-8');
const message = JSON.parse(messageString);
const message = JSON.parse(messageString, reviver);
this.state = 'process message';
this.onWorkerMessage(message, (err) => {
if (err) {
Expand Down
21 changes: 21 additions & 0 deletions src/serializer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export function replacer(_key, value) {
if (value instanceof RegExp) {
return {
__serialized_type: 'RegExp',
source: value.source,
flags: value.flags,
};
}
return value;
}

export function reviver(_key, value) {
if (typeof value === 'object' && value !== null) {
// eslint-disable-next-line no-underscore-dangle
if (value.__serialized_type === 'RegExp') {
return new RegExp(value.source, value.flags);
}
}

return value;
}
5 changes: 3 additions & 2 deletions src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import loaderRunner from 'loader-runner';
import asyncQueue from 'neo-async/queue';

import readBuffer from './readBuffer';
import { replacer, reviver } from './serializer';

const writePipe = fs.createWriteStream(null, { fd: 3 });
const readPipe = fs.createReadStream(null, { fd: 4 });
Expand Down Expand Up @@ -93,7 +94,7 @@ function writeJson(data) {
});

const lengthBuffer = Buffer.alloc(4);
const messageBuffer = Buffer.from(JSON.stringify(data), 'utf-8');
const messageBuffer = Buffer.from(JSON.stringify(data, replacer), 'utf-8');
lengthBuffer.writeInt32BE(messageBuffer.length, 0);

writePipeWrite(lengthBuffer);
Expand Down Expand Up @@ -319,7 +320,7 @@ function readNextMessage() {
return;
}
const messageString = messageBuffer.toString('utf-8');
const message = JSON.parse(messageString);
const message = JSON.parse(messageString, reviver);

onMessage(message);
setImmediate(() => readNextMessage());
Expand Down
1 change: 1 addition & 0 deletions test/sass-loader-example/assets/color_palette.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$white: #FFFFFF;
1 change: 1 addition & 0 deletions test/sass-loader-example/style.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import '_shared';
@import 'color_palette';

body {
background: red;
Expand Down
3 changes: 3 additions & 0 deletions test/sass-loader-example/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ module.exports = (env) => {
};
const sassLoaderOptions = {
sourceMap: true,
sassOptions: {
includePaths: [path.resolve(__dirname, 'assets')],
},
};
if (+env.threads > 0) {
threadLoader.warmup(workerPool, ['babel-loader', 'babel-preset-env']);
Expand Down
31 changes: 31 additions & 0 deletions test/serializer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const { replacer, reviver } = require('../src/serializer');

test('round-trips plain objects', () => {
const json = JSON.stringify(
{
a: 1,
b: 'foo',
c: [null, false],
},
replacer
);
expect(JSON.parse(json, reviver)).toEqual({
a: 1,
b: 'foo',
c: [null, false],
});
});

test('round-trips regular expressions', () => {
const json = JSON.stringify(
{
r: /hoge/g,
s: /^(\w\s)+$/m,
},
replacer
);
expect(JSON.parse(json, reviver)).toEqual({
r: /hoge/g,
s: /^(\w\s)+$/m,
});
});