Skip to content

Commit

Permalink
Make use of JS rest and spread operators throughout the codebase. NFC
Browse files Browse the repository at this point in the history
Following up on emscripten-core#21270.  These operators were introduced way before
our current default set of browser versions.  Anyone targeting an
browser so old as to not support these will already be on the
transpilation path.
  • Loading branch information
sbc100 committed Feb 7, 2024
1 parent c02cc3d commit 46dec93
Show file tree
Hide file tree
Showing 54 changed files with 131 additions and 145 deletions.
2 changes: 1 addition & 1 deletion src/cpuprofiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ var emscriptenCpuProfiler = {
var realf = 'real_' + f;
glCtx[realf] = glCtx[f];
var numArgs = this.webGLFunctionLength(f); // On Firefox & Chrome, could do "glCtx[realf].length", but that doesn't work on Edge, which always reports 0.
// Accessing 'arguments' is super slow, so to avoid overhead, statically reason the number of arguments.
// Accessing 'arguments'/'...' is super slow, so to avoid overhead, statically reason the number of arguments.
switch (numArgs) {
case 0: glCtx[f] = () => { this.enterSection(section); var ret = glCtx[realf](); this.endSection(section); return ret; }; break;
case 1: glCtx[f] = (a1) => { this.enterSection(section); var ret = glCtx[realf](a1); this.endSection(section); return ret; }; break;
Expand Down
42 changes: 19 additions & 23 deletions src/embind/embind.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ var LibraryEmbind = {
if (undefined === proto[methodName].overloadTable) {
var prevFunc = proto[methodName];
// Inject an overload resolver function that routes to the appropriate overload based on the number of arguments.
proto[methodName] = function() {
proto[methodName] = function(...args) {
// TODO This check can be removed in -O3 level "unsafe" optimizations.
if (!proto[methodName].overloadTable.hasOwnProperty(arguments.length)) {
throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${arguments.length}) - expects one of (${proto[methodName].overloadTable})!`);
if (!proto[methodName].overloadTable.hasOwnProperty(args.length)) {
throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`);
}
return proto[methodName].overloadTable[arguments.length].apply(this, arguments);
return proto[methodName].overloadTable[args.length].apply(this, args);
};
// Move the previous function into the overload table.
proto[methodName].overloadTable = [];
Expand Down Expand Up @@ -818,9 +818,9 @@ var LibraryEmbind = {
var argsWired = new Array(expectedArgCount);
var invokerFuncArgs = [];
var destructors = [];
var invokerFn = function() {
if (arguments.length !== expectedArgCount) {
throwBindingError(`function ${humanName} called with ${arguments.length} arguments, expected ${expectedArgCount}`);
var invokerFn = function(...args) {
if (args.length !== expectedArgCount) {
throwBindingError(`function ${humanName} called with ${args.length} arguments, expected ${expectedArgCount}`);
}
#if EMSCRIPTEN_TRACING
Module.emscripten_trace_enter_context(`embind::${humanName}`);
Expand All @@ -834,11 +834,11 @@ var LibraryEmbind = {
invokerFuncArgs[1] = thisWired;
}
for (var i = 0; i < expectedArgCount; ++i) {
argsWired[i] = argTypes[i + 2]['toWireType'](destructors, arguments[i]);
argsWired[i] = argTypes[i + 2]['toWireType'](destructors, args[i]);
invokerFuncArgs.push(argsWired[i]);
}

var rv = cppInvokerFunc.apply(null, invokerFuncArgs);
var rv = cppInvokerFunc(...invokerFuncArgs);

function onDone(rv) {
if (needsDestructorStack) {
Expand Down Expand Up @@ -896,11 +896,11 @@ var LibraryEmbind = {

#if EMBIND_AOT
var signature = createJsInvokerSignature(argTypes, isClassMethodFunc, returns, isAsync);
var invokerFn = InvokerFunctions[signature].apply(null, closureArgs);
var invokerFn = InvokerFunctions[signature](...closureArgs);
#else
let [args, invokerFnBody] = createJsInvoker(argTypes, isClassMethodFunc, returns, isAsync);
args.push(invokerFnBody);
var invokerFn = newFunc(Function, args).apply(null, closureArgs);
var invokerFn = newFunc(Function, args)(...closureArgs);
#endif
#endif
return createNamedFunction(humanName, invokerFn);
Expand Down Expand Up @@ -1765,18 +1765,18 @@ var LibraryEmbind = {
basePrototype = ClassHandle.prototype;
}

var constructor = createNamedFunction(name, function() {
var constructor = createNamedFunction(name, function(...args) {
if (Object.getPrototypeOf(this) !== instancePrototype) {
throw new BindingError("Use 'new' to construct " + name);
}
if (undefined === registeredClass.constructor_body) {
throw new BindingError(name + " has no accessible constructor");
}
var body = registeredClass.constructor_body[arguments.length];
var body = registeredClass.constructor_body[args.length];
if (undefined === body) {
throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${arguments.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`);
throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`);
}
return body.apply(this, arguments);
return body.apply(this, args);
});

var instancePrototype = Object.create(basePrototype, {
Expand Down Expand Up @@ -2197,14 +2197,12 @@ var LibraryEmbind = {
wrapperType = requireRegisteredType(wrapperType, 'wrapper');
properties = Emval.toValue(properties);

var arraySlice = [].slice;

var registeredClass = wrapperType.registeredClass;
var wrapperPrototype = registeredClass.instancePrototype;
var baseClass = registeredClass.baseClass;
var baseClassPrototype = baseClass.instancePrototype;
var baseConstructor = registeredClass.baseClass.constructor;
var ctor = createNamedFunction(constructorName, function() {
var ctor = createNamedFunction(constructorName, function(...args) {
registeredClass.baseClass.pureVirtualFunctions.forEach(function(name) {
if (this[name] === baseClassPrototype[name]) {
throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`);
Expand All @@ -2214,19 +2212,17 @@ var LibraryEmbind = {
Object.defineProperty(this, '__parent', {
value: wrapperPrototype
});
this["__construct"].apply(this, arraySlice.call(arguments));
this["__construct"](...args);
});

// It's a little nasty that we're modifying the wrapper prototype here.

wrapperPrototype["__construct"] = function __construct() {
wrapperPrototype["__construct"] = function __construct(...args) {
if (this === wrapperPrototype) {
throwBindingError("Pass correct 'this' to __construct");
}

var inner = baseConstructor["implement"].apply(
undefined,
[this].concat(arraySlice.call(arguments)));
var inner = baseConstructor["implement"](this, ...args);
detachFinalizer(inner);
var $$ = inner.$$;
inner["notifyOnDestruction"]();
Expand Down
2 changes: 1 addition & 1 deletion src/embind/emval.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ var LibraryEmVal = {
"};\n";

params.push(functionBody);
var invokerFunction = newFunc(Function, params).apply(null, args);
var invokerFunction = newFunc(Function, params)(...args);
#endif
var functionName = `methodCaller<(${types.map(t => t.name).join(', ')}) => ${retType.name}>`;
return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction));
Expand Down
8 changes: 4 additions & 4 deletions src/jsifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,9 @@ ${argConvertions}
if (LIBRARY_DEBUG && !isJsOnlySymbol(symbol)) {
snippet = modifyJSFunction(snippet, (args, body, async) => `\
function(${args}) {
var ret = (function() { if (runtimeDebug) err("[library call:${mangled}: " + Array.prototype.slice.call(arguments).map(prettyPrint) + "]");
var ret = (() => { if (runtimeDebug) err("[library call:${mangled}: " + Array.prototype.slice.call(arguments).map(prettyPrint) + "]");
${body}
}).apply(this, arguments);
})();
if (runtimeDebug && typeof ret != "undefined") err(" [ return:" + prettyPrint(ret));
return ret;
}`);
Expand Down Expand Up @@ -444,8 +444,8 @@ function(${args}) {
if (ASSERTIONS) {
assertion += `if (!${target} || ${target}.stub) abort("external symbol '${symbol}' is missing. perhaps a side module was not linked in? if this function was expected to arrive from a system library, try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment");\n`;
}
const functionBody = assertion + `return ${target}.apply(null, arguments);`;
LibraryManager.library[symbol] = new Function(functionBody);
const functionBody = assertion + `return ${target}(...args);`;
LibraryManager.library[symbol] = new Function('...args', functionBody);
isStub = true;
}
}
Expand Down
18 changes: 6 additions & 12 deletions src/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -2874,7 +2874,7 @@ addToLibrary({
#if ASSERTIONS
assert(ASM_CONSTS.hasOwnProperty(code), `No EM_ASM constant found at address ${code}. The loaded WebAssembly file is likely out of sync with the generated JavaScript.`);
#endif
return ASM_CONSTS[code].apply(null, args);
return ASM_CONSTS[code](...args);
},
emscripten_asm_const_int__deps: ['$runEmAsmFunction'],
Expand Down Expand Up @@ -2917,7 +2917,7 @@ addToLibrary({
#if ASSERTIONS
assert(ASM_CONSTS.hasOwnProperty(code), `No EM_ASM constant found at address ${code}. The loaded WebAssembly file is likely out of sync with the generated JavaScript.`);
#endif
return ASM_CONSTS[code].apply(null, args);
return ASM_CONSTS[code](...args);
},
emscripten_asm_const_int_sync_on_main_thread__deps: ['$runMainThreadEmAsm'],
emscripten_asm_const_int_sync_on_main_thread: (code, sigPtr, argbuf) => {
Expand Down Expand Up @@ -3100,7 +3100,7 @@ addToLibrary({
#endif
var f = Module['dynCall_' + sig];
#endif
return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr);
return f(ptr, ...args);
},
$dynCall__deps: ['$dynCallLegacy', '$getWasmTableEntry'],
#endif
Expand All @@ -3113,16 +3113,10 @@ addToLibrary({
#if ASSERTIONS && !DYNCALLS
assert(sig.includes('j') || sig.includes('p'), 'getDynCaller should only be called with i64 sigs')
#endif
var argCache = [];
return function() {
argCache.length = 0;
Object.assign(argCache, arguments);
return dynCall(sig, ptr, argCache);
};
return (...args) => dynCall(sig, ptr, args);
},
$dynCall__docs: '/** @param {Object=} args */',
$dynCall: (sig, ptr, args) => {
$dynCall: (sig, ptr, args = []) => {
#if MEMORY64
// With MEMORY64 we have an additional step to convert `p` arguments to
// bigint. This is the runtime equivalent of the wrappers we create for wasm
Expand All @@ -3145,7 +3139,7 @@ addToLibrary({
#if ASSERTIONS
assert(getWasmTableEntry(ptr), `missing table entry in dynCall: ${ptr}`);
#endif
var rtn = getWasmTableEntry(ptr).apply(null, args);
var rtn = getWasmTableEntry(ptr)(...args);
#endif
#if MEMORY64
return sig[0] == 'p' ? Number(rtn) : rtn;
Expand Down
2 changes: 1 addition & 1 deletion src/library_addfunction.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ addToLibrary({
];
// Write the overall length of the type section followed by the body
uleb128Encode(typeSectionBody.length, bytes);
bytes.push.apply(bytes, typeSectionBody);
bytes.push(...typeSectionBody);

// The rest of the module is static
bytes.push(
Expand Down
10 changes: 5 additions & 5 deletions src/library_async.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ addToLibrary({
}
#endif
#if ASSERTIONS && ASYNCIFY != 2 // We cannot apply assertions with stack switching, as the imports must not be modified from suspender.suspendOnReturnedPromise TODO find a way
imports[x] = function() {
imports[x] = (...args) => {
var originalAsyncifyState = Asyncify.state;
try {
return original.apply(null, arguments);
return original(...args);
} finally {
// Only asyncify-declared imports are allowed to change the
// state.
Expand Down Expand Up @@ -130,7 +130,7 @@ addToLibrary({
original = Asyncify.makeAsyncFunction(original);
}
#endif
ret[x] = function() {
ret[x] = (...args) => {
#if ASYNCIFY_DEBUG >= 2
dbg(`ASYNCIFY: ${' '.repeat(Asyncify.exportCallStack.length} try ${x}`);
#endif
Expand All @@ -143,9 +143,9 @@ addToLibrary({
// can just call the function with no args at all since and the engine will produce zeros
// for all arguments. However, for i64 arguments we get `undefined cannot be converted to
// BigInt`.
return original.apply(null, Asyncify.saveOrRestoreRewindArguments(x, arguments));
return original(...Asyncify.saveOrRestoreRewindArguments(x, args));
#else
return original.apply(null, arguments);
return original(...args);
#endif
#if ASYNCIFY == 1
} finally {
Expand Down
2 changes: 1 addition & 1 deletion src/library_ccall.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ addToLibrary({
// Data for a previous async operation that was in flight before us.
var previousAsync = Asyncify.currData;
#endif
var ret = func.apply(null, cArgs);
var ret = func(...cArgs);
function onDone(ret) {
#if ASYNCIFY == 1
runtimeKeepalivePop();
Expand Down
4 changes: 2 additions & 2 deletions src/library_dylink.js
Original file line number Diff line number Diff line change
Expand Up @@ -707,9 +707,9 @@ var LibraryDylink = {
// when first called.
if (!(prop in stubs)) {
var resolved;
stubs[prop] = function() {
stubs[prop] = (...args) => {
resolved ||= resolveSymbol(prop);
return resolved.apply(null, arguments);
return resolved(...args);
};
}
return stubs[prop];
Expand Down
6 changes: 3 additions & 3 deletions src/library_fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ FS.staticInit();` +

mounts.push(m);

check.push.apply(check, m.mounts);
check.push(...m.mounts);
}

return mounts;
Expand Down Expand Up @@ -1784,9 +1784,9 @@ FS.staticInit();` +
var keys = Object.keys(node.stream_ops);
keys.forEach((key) => {
var fn = node.stream_ops[key];
stream_ops[key] = function forceLoadLazyFile() {
stream_ops[key] = (...args) => {
FS.forceLoadFile(node);
return fn.apply(null, arguments);
return fn(...args);
};
});
function writeChunks(stream, buffer, offset, length, position) {
Expand Down
2 changes: 1 addition & 1 deletion src/library_glemu.js
Original file line number Diff line number Diff line change
Expand Up @@ -3580,7 +3580,7 @@ var LibraryGLEmulation = {
_glEnableVertexAttribArray(vaa);
}
for (var vaa in info.vertexAttribPointers) {
_glVertexAttribPointer.apply(null, info.vertexAttribPointers[vaa]);
_glVertexAttribPointer(...info.vertexAttribPointers[vaa]);
}
for (var attrib in info.enabledClientStates) {
_glEnableClientState(attrib|0);
Expand Down
2 changes: 1 addition & 1 deletion src/library_html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ var LibraryHTML5 = {
var call = JSEvents.deferredCalls[i];
JSEvents.deferredCalls.splice(i, 1);
--i;
call.targetFunction.apply(null, call.argsList);
call.targetFunction(...call.argsList);
}
},
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/library_html5_webgl.js
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ function handleWebGLProxying(funcs) {
funcBody = `${i}_before_on_calling_thread(${funcArgsString}); ` + funcBody;
}
funcArgs.push(funcBody);
funcs[i] = new (Function.prototype.bind.apply(Function, [Function].concat(funcArgs)));
funcs[i] = new (Function.prototype.bind.call(Function, Function, ...funcArgs));
} else if (targetingOffscreenFramebuffer) {
// When targeting only OFFSCREEN_FRAMEBUFFER, unconditionally proxy all GL calls to
// main thread.
Expand Down
8 changes: 3 additions & 5 deletions src/library_idbfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ addToLibrary({
},
DB_VERSION: 21,
DB_STORE_NAME: 'FILE_DATA',
mount: function(mount) {
// reuse all of the core MEMFS functionality
return MEMFS.mount.apply(null, arguments);
},
// reuse all of the core MEMFS functionality
mount: (...args) => MEMFS.mount(...args),
syncfs: (mount, populate, callback) => {
IDBFS.getLocalSet(mount, (err, local) => {
if (err) return callback(err);
Expand Down Expand Up @@ -110,7 +108,7 @@ addToLibrary({
}

if (FS.isDir(stat.mode)) {
check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path)));
check.push(...FS.readdir(path).filter(isRealDir).map(toAbsolute(path)));
}

entries[path] = { 'timestamp': stat.mtime };
Expand Down
6 changes: 3 additions & 3 deletions src/library_makeDynCall.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ addToLibrary({

var typeSection = [0x01 /* Type section code */];
uleb128Encode(typeSectionBody.length, typeSection); // length of section in bytes
typeSection.push.apply(typeSection, typeSectionBody);
typeSection.push(...typeSectionBody);
sections.push(typeSection);

var importSection = [
Expand Down Expand Up @@ -133,10 +133,10 @@ if (sig[0] === "j") {

var codeBody = [0x01]; // one code
uleb128Encode(convert_code.length, codeBody);
codeBody.push.apply(codeBody, convert_code);
codeBody.push(...convert_code);
var codeSection = [0x0A /* Code section code */];
uleb128Encode(codeBody.length, codeSection);
codeSection.push.apply(codeSection, codeBody);
codeSection.push(...codeBody);
sections.push(codeSection);

var bytes = new Uint8Array([].concat.apply([], sections));
Expand Down
2 changes: 1 addition & 1 deletion src/library_math.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ addToLibrary({
for (var i = 0; i < count; ++i) {
args.push({{{ makeGetValue('varargs', `i * ${getNativeTypeSize('double')}`, 'double') }}});
}
return Math.hypot.apply(null, args);
return Math.hypot(...args);
},
emscripten_math_sin: (x) => Math.sin(x),
emscripten_math_sinh: (x) => Math.sinh(x),
Expand Down
2 changes: 1 addition & 1 deletion src/library_nodefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ addToLibrary({
}
parts.push(node.mount.opts.root);
parts.reverse();
return PATH.join.apply(null, parts);
return PATH.join(...parts);
},
// This maps the integer permission modes from http://linux.die.net/man/3/open
// to node.js-specific file open permission strings at http://nodejs.org/api/fs.html#fs_fs_open_path_flags_mode_callback
Expand Down
Loading

0 comments on commit 46dec93

Please sign in to comment.