Skip to content

Commit de6efed

Browse files
committed
v0.5.10
1 parent ca933dc commit de6efed

18 files changed

+496
-599
lines changed

CHANGE.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## v0.5.10
2+
3+
- Module loader is improved.
4+
15
## v0.5.9
26

37
- Syntax of setting a field/setter is improved.

dist/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"type": "module",
33
"name": "@bitair/concurrent.js",
4-
"version": "0.5.9",
4+
"version": "0.5.10",
55
"description": "Easy Multithreading for JavaScript (Node.js, Deno & Browser)",
66
"main": "src/node/index.js",
77
"browser": "src/browser/index.js",

dist/src/browser/index.js

+89-116
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,20 @@ var ErrorMessage = {
4040
ObjectNotFound: { code: 505, text: "Couldn't find an object with the ID '%{1}'" },
4141
NotRunningOnWorker: { code: 506, text: "This module must be run on a worker." },
4242
WorkerNotSupported: { code: 507, text: "This browser doesn't support web workers." },
43-
ThreadAllocationTimeout: { code: 509, text: "Thread allocation failed due to timeout." }
43+
ThreadAllocationTimeout: { code: 509, text: "Thread allocation failed due to timeout." },
44+
MethodAssignment: { code: 509, text: "Can't assign a method." }
4445
};
4546
var ValueType = /* @__PURE__ */ ((ValueType2) => {
4647
ValueType2[ValueType2["Function"] = 1] = "Function";
47-
ValueType2[ValueType2["Any"] = 2] = "Any";
48+
ValueType2[ValueType2["Symbol"] = 2] = "Symbol";
49+
ValueType2[ValueType2["Any"] = 3] = "Any";
4850
return ValueType2;
4951
})(ValueType || {});
5052
var SYMBOL = {
5153
DISPOSE: Symbol("DISPOSE")
5254
};
5355

5456
// libs/platform/src/core/utils.ts
55-
function isFunction(val) {
56-
return typeof val === "function";
57-
}
58-
function isSymbol(val) {
59-
return typeof val === "symbol";
60-
}
6157
function format(str, args) {
6258
for (let i = 0; i < args.length; i++) {
6359
str = str.replace(`%{${i + 1}}`, args[i]);
@@ -116,113 +112,56 @@ var Task = class {
116112
}
117113
};
118114

115+
// libs/platform/src/core/threaded_function.ts
116+
var ThreadedFunction = class {
117+
constructor(moduleSrc, exportName, thread) {
118+
this.moduleSrc = moduleSrc;
119+
this.exportName = exportName;
120+
this.thread = thread;
121+
}
122+
static async create(pool, moduleSrc, exportName, execSettings) {
123+
const thread = await pool.getThread(execSettings.parallel);
124+
return new ThreadedFunction(moduleSrc, exportName, thread);
125+
}
126+
async invoke(args) {
127+
const task = Task.invokeFunction(this.moduleSrc, this.exportName, args);
128+
return this.thread.run(task);
129+
}
130+
};
131+
119132
// libs/platform/src/core/threaded_object.ts
120133
var ThreadedObject = class {
121-
constructor(pool) {
134+
constructor(pool, thread, id, propertyMap) {
122135
this.pool = pool;
136+
this.thread = thread;
137+
this.id = id;
138+
this.propertyMap = propertyMap;
123139
}
124-
thread;
125-
id;
126-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
127-
proxy = {};
128-
async init(moduleSrc, exportName, ctorArgs, execSettings) {
129-
this.thread = await this.pool.getThread(execSettings.parallel);
140+
static async create(pool, moduleSrc, exportName, ctorArgs, execSettings) {
141+
const thread = await pool.getThread(execSettings.parallel);
130142
const task = Task.instantiateObject(moduleSrc, exportName, ctorArgs);
131-
const [id, propertyTypeMap] = await this.thread.run(task);
132-
this.id = id;
133-
this.pool.registerObject(this, this.id, this.thread);
134-
const _this = this;
135-
return new Proxy(createShadowObject(propertyTypeMap), {
136-
get(target, key) {
137-
if (key === SYMBOL.DISPOSE)
138-
return _this.dispose.bind(_this);
139-
if (isSymbol(key))
140-
return void 0;
141-
const prop = Reflect.get(target, key);
142-
if (!isFunction(prop)) {
143-
if (prop instanceof Promise)
144-
return prop;
145-
return _this.getProperty.call(_this, key);
146-
} else {
147-
return (...params) => _this.invoke.call(_this, key, params);
148-
}
149-
},
150-
set(target, key, value) {
151-
if (isSymbol(key))
152-
return false;
153-
const setter = new Promise((resolve, reject) => {
154-
_this.setProperty.call(_this, key, value).then(() => {
155-
Reflect.set(target, key, void 0);
156-
resolve(value);
157-
}).catch((error) => reject(error));
158-
});
159-
Reflect.set(target, key, setter);
160-
return true;
161-
}
162-
});
143+
const [id, propertyMap] = await thread.run(task);
144+
const obj = new ThreadedObject(pool, thread, id, propertyMap);
145+
pool.registerObject(obj, id, thread);
146+
return obj;
163147
}
164-
async getProperty(methodName) {
165-
const thread = this.thread;
166-
const task = Task.getInstanceProperty(this.id, methodName);
167-
return await thread.run(task);
148+
async getProperty(propName) {
149+
const task = Task.getInstanceProperty(this.id, propName);
150+
return await this.thread.run(task);
168151
}
169-
async setProperty(methodName, value) {
170-
const thread = this.thread;
171-
const task = Task.setInstanceProperty(this.id, methodName, value);
172-
return await thread.run(task);
152+
async setProperty(propName, value) {
153+
const task = Task.setInstanceProperty(this.id, propName, value);
154+
return await this.thread.run(task);
173155
}
174156
async invoke(methodName, args) {
175-
const thread = this.thread;
176157
const task = Task.invokeInstanceMethod(this.id, methodName, args);
177-
return await thread.run(task);
158+
return await this.thread.run(task);
178159
}
179160
async dispose() {
180161
this.pool.unregisterObject(this);
181162
this.pool.disposeObject(this.id, this.thread);
182163
}
183164
};
184-
function createShadowObject(propertyTypeMap) {
185-
const obj = {};
186-
for (const key in propertyTypeMap) {
187-
if (Object.prototype.hasOwnProperty.call(propertyTypeMap, key)) {
188-
const propType = propertyTypeMap[key];
189-
const descriptor = {};
190-
if (propType === 1 /* Function */)
191-
descriptor.value = () => void 0;
192-
else
193-
descriptor.writable = true;
194-
descriptor.configurable = true;
195-
Object.defineProperty(obj, key, descriptor);
196-
}
197-
}
198-
return obj;
199-
}
200-
201-
// libs/platform/src/core/threaded_function.ts
202-
var ThreadedFunction = class {
203-
constructor(pool, moduleSrc, exportName, execSettings) {
204-
this.pool = pool;
205-
this.moduleSrc = moduleSrc;
206-
this.exportName = exportName;
207-
this.execSettings = execSettings;
208-
const _this = this;
209-
this.proxy = {
210-
async invoke(args) {
211-
return _this.invoke.call(_this, args);
212-
}
213-
};
214-
}
215-
thread;
216-
proxy;
217-
async invoke(args) {
218-
if (!this.thread) {
219-
const thread = await this.pool.getThread(this.execSettings.parallel);
220-
this.thread = thread;
221-
}
222-
const task = Task.invokeFunction(this.moduleSrc, this.exportName, args);
223-
return await this.thread.run(task);
224-
}
225-
};
226165

227166
// libs/platform/src/core/module_loader.ts
228167
var ModuleLoader = class {
@@ -231,29 +170,63 @@ var ModuleLoader = class {
231170
}
232171
async load(moduleSrc, execSettings) {
233172
const exports = await import(moduleSrc);
234-
const proxy = {};
235-
const _this = this;
236-
for (const exportName in exports) {
237-
if (Object.prototype.hasOwnProperty.call(exports, exportName)) {
238-
const _export = exports[exportName];
239-
if (isFunction(_export)) {
240-
proxy[exportName] = function ExportProxy(...params) {
241-
if (new.target) {
242-
const obj = new ThreadedObject(_this.pool);
243-
return obj.init(moduleSrc, exportName, params, execSettings);
244-
} else {
245-
const fn = new ThreadedFunction(_this.pool, moduleSrc, exportName, execSettings);
246-
return fn.proxy.invoke(params);
173+
const pool = this.pool;
174+
return new Proxy(exports, {
175+
get(target, key) {
176+
if (Reflect.has(target, key)) {
177+
const _export = Reflect.get(target, key);
178+
return new Proxy(_export, {
179+
construct(_target, args, newTarget) {
180+
return createConstructorProxy(pool, moduleSrc, newTarget.name, args, execSettings);
181+
},
182+
apply(target2, _thisArg, args) {
183+
return createFunctionProxy(pool, moduleSrc, target2.name, args, execSettings);
247184
}
248-
};
185+
});
249186
} else {
250-
proxy[exportName] = _export;
187+
return Reflect.get(target, key);
251188
}
252189
}
253-
}
254-
return proxy;
190+
});
255191
}
256192
};
193+
async function createFunctionProxy(pool, moduleSrc, exportName, args, execSettings) {
194+
const fn = await ThreadedFunction.create(pool, moduleSrc, exportName, execSettings);
195+
return fn.invoke(args);
196+
}
197+
async function createConstructorProxy(pool, moduleSrc, exportName, args, execSettings) {
198+
const obj = await ThreadedObject.create(pool, moduleSrc, exportName, args, execSettings);
199+
return new Proxy(obj.propertyMap, {
200+
get(target, key) {
201+
if (key === SYMBOL.DISPOSE)
202+
return obj.dispose.bind(obj);
203+
if (!Reflect.has(target, key))
204+
return void 0;
205+
const prop = Reflect.get(target, key);
206+
if (prop instanceof Promise)
207+
return prop;
208+
if (obj.propertyMap[key] === 1 /* Function */) {
209+
return (...params) => obj.invoke(key, params);
210+
} else {
211+
return obj.getProperty(key);
212+
}
213+
},
214+
set(target, key, value) {
215+
if (!Reflect.has(target, key))
216+
return false;
217+
if (obj.propertyMap[key] === 1 /* Function */)
218+
throw new ConcurrencyError(ErrorMessage.MethodAssignment);
219+
const setter = new Promise((resolve, reject) => {
220+
obj.setProperty(key, value).then(() => {
221+
Reflect.set(target, key, 3 /* Any */);
222+
resolve(value);
223+
}).catch((error) => reject(error));
224+
});
225+
Reflect.set(target, key, setter);
226+
return true;
227+
}
228+
});
229+
}
257230

258231
// libs/platform/src/core/coroutine.ts
259232
var _Coroutine = class {

dist/src/browser/worker_script.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ var ErrorMessage = {
77
ObjectNotFound: { code: 505, text: "Couldn't find an object with the ID '%{1}'" },
88
NotRunningOnWorker: { code: 506, text: "This module must be run on a worker." },
99
WorkerNotSupported: { code: 507, text: "This browser doesn't support web workers." },
10-
ThreadAllocationTimeout: { code: 509, text: "Thread allocation failed due to timeout." }
10+
ThreadAllocationTimeout: { code: 509, text: "Thread allocation failed due to timeout." },
11+
MethodAssignment: { code: 509, text: "Can't assign a method." }
1112
};
1213
var SYMBOL = {
1314
DISPOSE: Symbol("DISPOSE")
@@ -170,7 +171,7 @@ function getPropertyTypeMap(obj) {
170171
if (!isSymbol(key)) {
171172
if (!map[key]) {
172173
const descriptor = Reflect.getOwnPropertyDescriptor(obj, key);
173-
map[key] = isFunction(descriptor.value) ? 1 /* Function */ : 2 /* Any */;
174+
map[key] = isFunction(descriptor.value) ? 1 /* Function */ : 3 /* Any */;
174175
}
175176
}
176177
}

0 commit comments

Comments
 (0)