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.
npm install jsdc
Set
和Map
)请使用es6-shim
之类的库npm install
安装依赖homunculus
:https://github.com/army8735/homunculus[MIT License]
0b
或0B
开头的二进制将使用parseInt
转换:
var i = 0b010, j = 0B101
var i = parseInt("0b010", 2), j = parseInt("0B101", 2)
0o
或0O
开头的八进制也是如此(有人会用大写的字母O吗,和数字0根本看不出来区别):
var i = 0o456, j = 0O777
var i = parseInt("0o456", 8), j = parseInt("0O777", 8)
将var
申明迁移至最近的作用域起始处:
function() {
if(true) {
var a = 1;
let b = 2;
}
}
function() {var a;
if(true) {
a = 1;
let b = 2;
}
}
仅当必要时才迁移,否则保持原样(比如下面没有let
):
function() {
if(true) {
var a = 1;
}
}
示例中
let
和块级作用域尚未处理,后面会提到。
函数和var的性质一样,除了迁移还会改写为var形式:
{function a(){}}
var a;{a=function (){}}
必要时将{}
替换为function
作用域:
{
let a = 1;
function b(){}
}
var b;!function() {
let a = 1;
b=function (){}
}();
if
语句,iterator
语句和try
/catch
/finally
等也是,注意和纯{}
语句插入匿名函数位置的异同:
if(true) {
let a = 1;
}
if(true) {!function() {
let a = 1;
}();}
示例中
let
尚未做处理,后面会提到。
将let
和const
替换为var
:
let a = 1;
const b;
var a = 1;
var b;
注意和块级作用域的交互:
{
var a = 1;
let b;
const c = 1;
}
var a;!function() {
a = 1;
var b;
var c = 1;
}();
根据是否undefined
赋值,它可以有多个:
function method(a, b = 1) {
}
function method(a, b ) {if(typeof b == "undefined") b = 1;
}
将扩展参数通过arguments
转换为数组:
function method(a, ...args) {
}
function method(a, args) {args = [].slice.call(arguments, 1);
}
方法执行则使用apply
调用:
fn(a, b, ...c)
fn.apply(this, [a,b].concat(c))
如果调用者是成员表达式,context将从this
变为主表达式:
Math.max(...a)
Math.max.apply(Math, [].concat(a))
将模板转换为普通字符串,需要的情况下会包裹括号(确保运算符优先级正确性):
`template`
"template"
模板中的引号将被转义:
`"`
"\""
模板中的变量会被替换:
`${a}b`
(a + "b")
注意变量标识符$也可以被转义:
`\${a}b`
"\${a}b"
将of
改为in
:
for(a of b){}
for(a in b){}
循环体内复制将键改为值:
for(a of b){}
for(a in b){a = b[a];}
var
语句同样处理:
for(var a of b){}
for(var a in b){a = b[a];}
将类声明改为function
声明:
class A{}
function A(){}
constructor
构造函数可省略,也可以显示声明:
class A{
constructor(a){this.a = a}
}
//此行是空行,请忽略:由于github会忽略前面的空白,所以用注释代替
function A(a){this.a = a}
注意行对应关系,省略的话行位置是
class
声明行,否则是constructor
声明行。
方法会改写成prototype
的原型方法:
class A{
method(){}
}
function A{}
A.prototype.method=function(){}
getter/setter会巧妙地设置到原型上:
class A{
get b(){}
set c(d){}
}
function A(){}
A.prototype.b={get b(){}}["b"];
A.prototype.c={set c(d){}}["c"];
static
静态属性会附加在function
本身:
class A{
static a(){}
}
function A(){}
A.a=function(){}
采用最广泛的寄生组合式继承:
class A extends B{
constructor(){}
}
function A(){}!function(){var _=Object.create(B.prototype);_.constructor=A;A.prototype=_;}();
function A(){}
Object.keys(B).forEach(function(k){A[k]=B[k]});
开头会附加上一段
prototype
原型和constructor
构造器,标准的寄生组合式继承方法。 结尾会继承父类的静态属性。
super
关键字直接改写为父类引用:
class A extends B{
constructor(){super()}
}
function A(){}!function(){var _=Object.create(B.prototype);_.constructor=A;A.prototype=_;}();
function A(){B.call(this)}
Object.keys(B).forEach(function(k){A[k]=B[k]});
如果不是调用父类构造函数而是方法,则不会添加call
:
class A extends B{
constructor(){super.a()}
}
function A(){}!function(){var _=Object.create(B.prototype);_.constructor=A;A.prototype=_;}();
function A(){B.a()}
Object.keys(B).forEach(function(k){A[k]=B[k]});
和函数表达式一样,class也可以有表达式:
var o = class{
method(){}
}
var o = function(){function __0__(){}
__0__.prototype.method = function(){}
return __0__}()
由于表达式没有名字(也可以有),所以需要封装成立即执行的匿名函数并返回一个
class
声明
有名字的话就用原有名字,否则依然临时唯一id
注意匿名函数的结尾没有分号,因为本身是个
assignmentexpr
只要出现了module/import/export语句,就认为文件是个模块,用define
封装成AMD/CMD模块:
module circle from "a"
define(function(requrie,exports,module){module circle from "a"});
注意语句本身尚未做处理,下面会说明。为阅读方便,下面所有都省略了
define
封装
也可以通过API设置来控制:
jsdc.define(wrap:Boolean):Boolean
module
转换为require
:
module circle from "a"
var circle=require("a");
import
也会转换为require
:
import "a"
require("a");
import
可以指定id:
import a from "a"
var a;!function(){var __0__=require("a");a=__0__.a}();
类似
__0__
变量是自动生成的,数字会自动累加,且不会和已有变量冲突。
在冲突时会自动跳过:
import __0__ from "a"
var __0__;!function(){var __1__=require("a");__0__=__1__.a}();
import
还可以指定多个id:
import a,b from "a"
var a;var b;!function(){var __0__=require("a");a=__0__.a;b=__0__.b;}();
import
可以用{}
来赋值,注意里面as
声明变量名的方法:
import {a,b as c} from "a"
var a;var c;!function(){var __0__=require("a");a=__0__.a;c=__0__.b;}();
export *
会赋给module.exports:
export * from "a"
module.exports=require("a");
export
一个var
语句时会自动赋值同名变量:
export var a = 1
var a;exports.a=a = 1
export
一个方法或类时也一样:
export function a(){}
export class A{}
exports.a=a;function a(){}
exports.A=A;function A(){}
export default
会直接赋给module.exports
:
export default a
module.exports=a
可以代替Array.map
方法:
var a = [for(k of o)k]
var a = function(){var k;var __0__=[];for(k in o){k=o[k];__0__.push(k)}return __0__}()
注意再次出现的临时变量
__0__
和上面提到的一致,不会冲突。
if
语句可以替代Array.filter
方法:
var a = [for(k of o)if(k)k]
var a = function(){var k;var __0__=[];for(k in o){k=o[k];if(k)__0__.push(k)}return __0__}()
嵌套组合使用也是可以的:
var a = [for(a of b)for(c of a)if(c)c]
var a = function(){var a;var c;var __0__=[];for(a in b){a=b[a];for(c in a){c=a[c];if(c)__0__.push(c)}}return __0__}()
转换为普通函数:
var a = v => v
var a = function(v) {return v}
括号形式的参数:
var a = (b, c) => b + c
var a = function(b, c) {return b + c}
带{}
的函数体:
var a = (b, c) => {return b - c}
var a = function(b, c) {return b - c}
yield
作为关键字只能出现在Generator
中,会被替换为return
:
function *a() {
yield
}
function *a() {
return
}
Generator
语句本身尚未做处理,后面会提到。
它的实现比较复杂,首先是改写为普通函数:
function *a(){
yield 1
yield 2
}
function a(){
return 1
return 2
}
然后包裹:
function *a(){
yield 1
yield 2
}
var a=function(){return function (){return {next:a}};function a(){
return 1
return 2
}}();
这样每次调用它便能得到像es6中一样的一个具有
next()
方法的对象。
内部的a变量需要改写为一个唯一临时id(为什么后面会提到):
function *a(){
yield 1
yield 2
}
var a=function(){return function (){return {next:__0__}};function __0__(){
return 1
return 2
}}();
再次添加一个唯一临时id作为state标识,来为实现yield
功能做准备:
function *a(){
yield 1
yield 2
}
var a=function(){var __1__=0;return function (){return {next:__0__}};function __0__(){
return 1
return 2
}}();
当出现yield
语句时,添加switch
语句来模拟顺序执行:
function *a(){
yield 1
yield 2
}
var a=function(){var __1__=0;return function (){return {next:__0__}};function __0__(){
switch(__1__++){case 0:return 1
case 1:return 2}
}}();
同时函数里面的var
声明需要前置,以免每次调用next()
方法时又重新声明一遍失去了状态:
function *a(){
var a = 1;
yield a++;
yield a++;
}
var a=function(){var __1__=0;return function (){return {next:__0__}};var a;function __0__(){
switch(__1__++){case 0:a = 1;
return a++;
case 1:return a++;}
}}();
函数则不需要前置。 注意函数内有个同名变量
a
,这就是前面为什么要改函数名的原因。
待续……
FAQs
compiler ecmascript6 to ecmascript5
The npm package jsdc receives a total of 13 weekly downloads. As such, jsdc popularity was classified as not popular.
We found that jsdc 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.