Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
babel-plugin-named-params
Advanced tools
Babel Plugin for Named Function Parameters
This is a Babel transpiler plugin for transforming non-standard named function parameters in ECMAScript 2015 source code. In particular, it transpiles the following input constructs...
fn(a = "foo", 42, d = "bar", 7)
baz.quux.fn(a = "foo", 42, d = "bar", 7)
...to the output constructs...
T(undefined, fn, [ 42, 7 ], { a: "foo", d: "bar" })
T(baz.quux, baz.quux.fn, [ 42, 7 ], { a "foo", d: "bar" })
...where T
is the "trampoline" function
of the corresponding run-time module
babel-runtime-named-params
.
Assuming the function fn
was declared as function fn (a, b, c, d) { ... }
, these output constructs under run-time finally translate into...
fn.apply(undefined, [ "foo", 42, 7, "bar" ])
baz.quux.fn.apply(baz.quux, [ "foo", 42, 7, "bar" ])
...or the equivalent of the regular calls:
fn("foo", 42, 7, "bar")
baz.quux.fn("foo", 42, 7, "bar")
This plugin is motivated by the wish of the author to have a more elegant approach to named parameters in JavaScript than the usual convention of passing an object argument provides. For such a conventional ECMAScript 2018 function declaration...
function foo (arg1, arg2, options) {
let { opt1, opt2 } = { opt1: "def1", opt2: "def2", ...options }
console.log(arg1, arg2, opt1, opt2)
}
...in addition, to the regular usage...
foo("val1", "val2", { opt1: "val3", opt2: "val4" })
// -> "val1", "val2", "val3", "val4"
...you can now use it with less boilerplate...
foo("val1", "val2", opt1 = "val3", opt2 = "val4")
// -> "val1", "val2", "val3", "val4"
...and even make the function declaration more elegant:
function foo (arg1, arg2, opt1 = "def1", opt2 = "def2") {
console.log(arg1, arg2, opt1, opt2)
}
Additionally, similar to Unix command-line option arguments (-x
or
--xx
), which most of the time can be mixed with positional arguments,
one can now mix named and positional function arguments, too.
The following particular features are provided:
Parameter Syntax: Named parameters are syntax-wise just ECMAScript assignment expressions
<identifier> = <expression>
inside function argument lists.
But instead of assigning to a variable in the lexical scope of the
function call, this now assigns to a parameter of the function call.
Parameter Ordering: Named and positional parameters can be provided in an arbitrary order.
For a function declaration function fn (a, b, c) { ... }
all of the
following function calls result in a call fn(x, y, z)
:
fn(a = x, b = y, c = z) // named parameters only
fn(x, b = y, z) // mixed parameters only (in positional order)
fn(b = y, x, z) // mixed parameters only (in arbitrary order)
fn(x, z, b = y) // mixed parameters only (in arbitrary order)
In other words, the algorithm for determining the function call
parameters is: first, the parameters (names and positions) of
the target function are determined via the function source code
(Function.prototype.toString()
). Second, all named parameters are
translated to resulting positional parameters at their particular
positions. Third, all original positional parameters are translated to
resulting positional parameters at still unused positions (from left
to right). All remaining unused positions are filled with the value undefined
.
Options Parameter: In the JavaScript world, there is the convention of
having an options
function parameter which receives an object of
options. In case a named parameter in the function call is not found
in the function declaration, but such an options parameter exists,
the named parameter is passed as an option parameter field. For a
function declaration function fn (a, b, c, options) { ... }
all of
the following function calls result in a call fn(x, y, z, { foo: 42, bar: 7 })
:
fn(x, y, z, options = { foo: 42, bar: 7 }) // explicit options parameter (in positional order)
fn(options = { foo: 42, bar: 7 }, x, y, z) // explicit options parameter (in arbitrary order)
fn(x, y, z, foo = 42, bar = 7) // options as named parameters
fn(foo = 42, bar = 7, x, y, z) // options as named parameters
fn(x, y, z, options = { foo: 42 }, baz = 7) // explicit and implicit options
fn(x, y, z, baz = 7, options = { foo: 42 }) // explicit and implicit options
fn(a = x, b = y, c = z, foo = 42, bar = 7) // everything as named parameters
Function Declaration and Transpilation: Although the named parameters need
a Babel-based transpilation theirself, the function declarations
should not be transpiled to a target environment below ECMAScript
2015, as Babel would remove parameters with defaults from the
function declaration. To be able to use function declarations of the
form fn (a, b, c = def1, d = def2) { ... }
you have to at least
target an ECMAScript 2015 environment like Node 6 with the help of
@babel/preset-env
or the underlying func-params
utility function
will to be able to determine the c
and d
parameters.
Increased Code Size: As the determination of function parameters is done under run-time (to support arbitrary existing code which is not part of the transpilation process itself), the resulting code size of your application increased by about 26KB. This is harmless for applications and libraries in the Node environments or applications in Browser environments, but can hurt you for libraries in Browser environments. Hence, try to not use this feature for libraries intended to be used in Browser environments or accept that their size increases by about 26KB.
Decreased Run-Time Performance: As the determination of function parameters is done under run-time (to support arbitrary existing code which is not part of the transpilation process itself), the run-time performance decreases somewhat. At least on the first function invocation. Internally, the source code of the target function is parsed and the result cached in memory. So, on the first function invocation, the parsing causes the function invocation to be much slower than the regular invocation, while on the second and all subsequent function invocation, the indirect function invocation is just slightly slower than the regular invocation.
Assignment Expression: As explained above, this plugin changes the
semantics of the assignment expressions inside function argument
lists. By definition, in foo(id = expr)
the expr
is assigned to a
variable with the identifier id
in the lexical scope of the function
call. With this plugin, this is no longer the case. Now expr
is
assigned to the parameter with the identifier id
in the function
declaration. This is a change is semantics, of course. On the other
hand, an assignment expression inside a function argument list could
be considered a strange coding practice anyway.
$ npm install @babel/core
$ npm install @babel/preset-env
$ npm install babel-plugin-named-params
$ npm install babel-runtime-named-params
.babelrc
:{
"presets": [
[ "@babel/preset-env", {
"targets": {
"node": "6.0"
}
} ]
],
"plugins": [
[ "named-params", {
"options": true,
"caching": true
} ]
]
}
sample.js
:const f1 = (a, b, c = "foo", d = "bar") => {
console.log(`a=<${a}> b=<${b}> c=<${c}> d=<${d}>`)
}
f1(1, 2, 3, 4)
f1(1, 2, d = "4", 3)
f1(1, 2, d = "4", c = "3")
f1(a = "1", 2, c = "3", d = "4")
const f2 = (a, b, options = {}) => {
console.log(`a=<${a}> b=<${b}> options=<${JSON.stringify(options)}>`)
}
f2(1, 2)
f2(1, 2, { foo: "bar", baz: "quux" })
f2(1, 2, options = { foo: "bar", baz: "quux" })
f2(1, 2, foo = "bar", baz = "quux")
f2(1, 2, baz = "quux", options = { foo: "bar" })
$ babel-node sample.js
a=<1> b=<2> c=<3> d=<4>
a=<1> b=<2> c=<3> d=<4>
a=<1> b=<2> c=<3> d=<4>
a=<1> b=<2> c=<3> d=<4>
a=<1> b=<2> options=<{}>
a=<1> b=<2> options=<{"foo":"bar","baz":"quux"}>
a=<1> b=<2> options=<{"foo":"bar","baz":"quux"}>
a=<1> b=<2> options=<{"foo":"bar","baz":"quux"}>
a=<1> b=<2> options=<{"foo":"bar","baz":"quux"}>
Copyright (c) 2018-2021 Dr. Ralf S. Engelschall (http://engelschall.com/)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
FAQs
Babel Plugin for Named Function Parameters
The npm package babel-plugin-named-params receives a total of 17 weekly downloads. As such, babel-plugin-named-params popularity was classified as not popular.
We found that babel-plugin-named-params demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.