Skip to content

Commit

Permalink
fix: check constant violation inside loops (#15019)
Browse files Browse the repository at this point in the history
Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>

Co-authored-by: Janie <janiewang26@gmail.com>
  • Loading branch information
nicolo-ribaudo and janiewang26 committed Oct 8, 2022
1 parent 8e9ae5f commit cf0cfac
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 6 deletions.
20 changes: 14 additions & 6 deletions packages/babel-plugin-transform-block-scoping/src/index.ts
@@ -1,5 +1,5 @@
import { declare } from "@babel/helper-plugin-utils";
import type { NodePath, Visitor, Scope } from "@babel/traverse";
import type { NodePath, Visitor, Scope, Binding } from "@babel/traverse";
import { visitor as tdzVisitor } from "./tdz";
import type { TDZVisitorState } from "./tdz";
import { traverse, template, types as t } from "@babel/core";
Expand Down Expand Up @@ -487,13 +487,21 @@ class BlockScoping {
}

checkConstants() {
const scope = this.scope;
const state = this.state;
const constBindings = new Map<string, Binding>();

// In some cases, there are two different scopes: for example,
// for (const x of y) {} has a scope for the loop head and one
// for the body.
for (const scope of new Set([this.scope, this.blockPath.scope])) {
for (const name of Object.keys(scope.bindings)) {
const binding = scope.bindings[name];
if (binding.kind === "const") constBindings.set(name, binding);
}
}

for (const name of Object.keys(scope.bindings)) {
const binding = scope.bindings[name];
if (binding.kind !== "const") continue;
const { state } = this;

for (const [name, binding] of constBindings) {
for (const violation of binding.constantViolations) {
const readOnlyError = state.addHelper("readOnlyError");
const throwNode = t.callExpression(readOnlyError, [
Expand Down
@@ -0,0 +1,11 @@
expect(function () {
for (const element = 1; element++;) break;
}).toThrow('"element" is read-only');

expect(function () {
for (;;) {
const from = 50;
from--;
break;
}
}).toThrow('"from" is read-only');
@@ -0,0 +1,4 @@
for (const element = 1; element++;) {
const from = 50;
from--;
}
@@ -0,0 +1,4 @@
for (var element = 1; +element, babelHelpers.readOnlyError("element");) {
var from = 50;
+from, babelHelpers.readOnlyError("from");
}
@@ -0,0 +1,7 @@
expect(function () {
const array = [1, 2, 3];
for (const element of array) {
const from = 50;
from--;
}
}).toThrow('"from" is read-only');
@@ -0,0 +1,4 @@
for (const element of []) {
const from = 50;
from--;
}
@@ -0,0 +1,4 @@
for (var element of []) {
var from = 50;
+from, babelHelpers.readOnlyError("from");
}

0 comments on commit cf0cfac

Please sign in to comment.