Skip to content

Commit

Permalink
add babel-plugin-transform-block-scoping
Browse files Browse the repository at this point in the history
A discussion in evanw/esbuild#478 has shown
that using let and class in same enclosing level has a signigicant
performance impact on the Safari browser. To alleviate this problem we
transform the let and class constructs into var when it is 'easily'
possible.

Co-authored-by: Justin Ridgewell <[email protected]>
Co-authored-by: erwin mombay <[email protected]>
  • Loading branch information
erwinmombay and jridgewell committed Oct 21, 2020
1 parent 6418ea9 commit c8dc2ab
Show file tree
Hide file tree
Showing 12 changed files with 352 additions and 0 deletions.
1 change: 1 addition & 0 deletions build-system/babel-config/post-closure-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function getPostClosureConfig() {
'./build-system/babel-plugins/babel-plugin-const-transformer',
'./build-system/babel-plugins/babel-plugin-transform-remove-directives',
'./build-system/babel-plugins/babel-plugin-transform-stringish-literals',
'./build-system/babel-plugins/babel-plugin-transform-block-scoping',
];
return {
compact: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Copyright 2020 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

module.exports = function ({template, types: t}) {
return {
name: 'block-scoping', // not required
visitor: {
ClassDeclaration(path) {
const {node, scope} = path;
const {id} = node;
if (!id) {
return;
}

const {name} = id;
const uid = scope.generateUid(name);
path.scope.rename(name, uid);

node.type = 'ClassExpression';
node.id = null;
path.replaceWith(template.statement.ast`var ${uid} = ${node}`);
},

VariableDeclaration(path) {
const {node, scope} = path;
if (node.kind !== 'let') {
return;
}

const parent = path.findParent((p) => {
return p.isBlockParent() && !p.isBlockStatement();
});
const bindings = Object.keys(
t.getBindingIdentifiers(node, false, true)
);

if (parent.isLoop()) {
for (const name of bindings) {
const references = scope.getBinding(name).referencePaths;
for (const ref of references) {
const p = ref.findParent((p) => {
return p === parent || p.isFunction() || p.isProgram();
});
if (p !== parent && p.isFunction()) {
return;
}
}
}
}

for (const name of bindings) {
scope.rename(name);
}
node.kind = 'var';
},
},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright 2020 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class A {
method1() {}
method2() {}
static staticMethod1() {}
}

{
new A();
class A {
method1() {}
method2() {}
static staticMethod1() {}
}
new A();
}

function hello() {
new A();
class A {
method1() {}
method2() {}
static staticMethod1() {}
}
new A();
}

new A();
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["../../../.."]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright 2020 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var _A = class {
method1() {}

method2() {}

static staticMethod1() {}

};

{
new _A2();

var _A2 = class {
method1() {}

method2() {}

static staticMethod1() {}

};

new _A2();
}

function hello() {
new _A3();

var _A3 = class {
method1() {}

method2() {}

static staticMethod1() {}

};

new _A3();
}

new _A();
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright 2020 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const a = 'abc';

{
const a = 'xyz';
}

function test() {
const a = 1;
{
const a = 2;
const b = 2;
}
}

const z = [];

for (const i = 0; i < 10; i++) {
z.push(function() {
return function() {
console.log(i);
};
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["../../../.."]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright 2020 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const a = 'abc';
{
const a = 'xyz';
}

function test() {
const a = 1;
{
const a = 2;
const b = 2;
}
}

const z = [];

for (const i = 0; i < 10; i++) {
z.push(function () {
return function () {
console.log(i);
};
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright 2020 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
let a = 'abc';
{
let a = 'xyz';
console.log(a);
}
console.log(a);

function test() {
let a = 1;
{
let a = 2;
console.log(a);
}
console.log(a);
}

let z = [];

for (let i = 0; i < 10; i++) {
z.push(function() {
return function() {
console.log(i);
};
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["../../../.."]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright 2020 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var _a = 'abc';
{
var _a2 = 'xyz';
console.log(_a2);
}
console.log(_a);

function test() {
var _a3 = 1;
{
var _a4 = 2;
console.log(_a4);
}
console.log(_a3);
}

var _z = [];

for (let i = 0; i < 10; i++) {
_z.push(function () {
return function () {
console.log(i);
};
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright 2020 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

const runner = require('@babel/helper-plugin-test-runner').default;

runner(__dirname);

0 comments on commit c8dc2ab

Please sign in to comment.