Skip to content

Commit 8cebb95

Browse files
committed
Disallow object and array literals, cleanup hasProps
1 parent 5395193 commit 8cebb95

File tree

11 files changed

+76
-25
lines changed

11 files changed

+76
-25
lines changed

src/index.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,8 @@ export default function (babel) {
684684
const fnAST = babel.template(fn.toString())({
685685
[helperName]: uid,
686686
});
687+
fnAST._compact = true;
688+
fnAST._generated = true;
687689
helpers.push(fnAST);
688690
}
689691
insertAfterImports(path, helpers);
@@ -850,6 +852,11 @@ export default function (babel) {
850852
} else if (path.isLiteral() || isUndefined(path) || isSignedNumber(path)) {
851853
const isEq = t.binaryExpression("===", argRef, path.node);
852854
path.replaceWith(isEq);
855+
} else if (path.isObjectExpression() || path.isArrayExpression()) {
856+
throw path.buildCodeFrameError(
857+
"LightScript does not yet support matching on object or array literals. " +
858+
"To destructure, use `with` (eg; `| with { foo, bar }: foo + bar`)."
859+
);
853860
}
854861
}
855862

@@ -896,7 +903,7 @@ export default function (babel) {
896903
}
897904
}
898905

899-
const isObjCall = t.callExpression(isObjUid, [argRef, t.arrayExpression(propsToCheck)]);
906+
const isObjCall = t.callExpression(isObjUid, [argRef, ...propsToCheck]);
900907
test = buildAnd(test, isObjCall);
901908

902909
for (const [ propName, childPatternPath, defaultObj = null ] of childPatterns) {

src/stdlib.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ export const lightscriptImports = {
1212
};
1313

1414
export const runtimeHelpers = {
15-
hasProps: function hasProps(obj, props) {
16-
return (
17-
obj != null &&
18-
(typeof obj === "object" || typeof obj === "function") &&
19-
props.filter(prop => prop in obj).length === props.length
20-
);
15+
hasProps: function hasProps(obj) {
16+
if (obj == null) return false;
17+
if (typeof obj !== "object" && typeof obj !== "function") return false;
18+
let i = arguments.length;
19+
while (--i > 0) {
20+
if (!(arguments[i] in obj)) return false;
21+
}
22+
return true;
2123
},
2224
hasLength: function hasLength(arr, minLength, maxLength) {
2325
minLength = minLength || 0;

test/fixtures/match/arr-pattern/expected.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
function _hasLength(arr, minLength, maxLength) {
2-
minLength = minLength || 0;
3-
maxLength = maxLength != null ? maxLength : Number.MAX_SAFE_INTEGER;
4-
return arr != null && typeof arr !== "function" && arr.length === arr.length | 0 && arr.length >= minLength && arr.length <= maxLength;
5-
}
1+
function _hasLength(arr, minLength, maxLength) { minLength = minLength || 0; maxLength = maxLength != null ? maxLength : Number.MAX_SAFE_INTEGER; return arr != null && typeof arr !== "function" && arr.length === arr.length | 0 && arr.length >= minLength && arr.length <= maxLength; }
62

73
if (_hasLength(x, 0, 0)) {
84
const [] = x;
@@ -24,4 +20,4 @@ if (_hasLength(x, 0, 0)) {
2420
const [[b, d = 'e'], [g,, h], ...j] = x;
2521

2622
[b, d, g, ...j].join('');
27-
}
23+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
match x:
2+
| 1 or [a, b]: "not allowed"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"throws": "LightScript does not yet support matching on object or array literals. To destructure, use `with` (eg; `| with { foo, bar }: foo + bar`)."
3+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
match x:
2+
| 1 or { a, b: 1 }: "not allowed"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"throws": "LightScript does not yet support matching on object or array literals. To destructure, use `with` (eg; `| with { foo, bar }: foo + bar`)."
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
match x:
2+
| with { a, aa: [b, { c = 1 }, ...d] }:
3+
d.concat(a + b + c)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
m(x) -> match x:
2+
| with { a, aa: [b, { c = 1 }, ...d] }:
3+
d.concat(a + b + c)
4+
5+
assert.equal(
6+
undefined,
7+
m()
8+
)
9+
assert.equal(
10+
undefined,
11+
m({ a: 1 })
12+
)
13+
assert.equal(
14+
undefined,
15+
m({ a: 1, aa: [ 2 ] })
16+
)
17+
assert.deepEqual(
18+
[4],
19+
m({ a: 1, aa: [ 2, [ 3 ] ] }) // womp, arrays are objects
20+
)
21+
assert.deepEqual(
22+
[5],
23+
m({ a: 1, aa: [ 2, { c: 2 } ] })
24+
)
25+
assert.deepEqual(
26+
[7, 5],
27+
m({ a: 1, aa: [ 2, { c: 2 }, 7 ] })
28+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function _hasProps(obj) { if (obj == null) return false; if (typeof obj !== "object" && typeof obj !== "function") return false; var i = arguments.length; while (--i > 0) { if (!(arguments[i] in obj)) return false; } return true; }
2+
3+
function _hasLength(arr, minLength, maxLength) { minLength = minLength || 0; maxLength = maxLength != null ? maxLength : Number.MAX_SAFE_INTEGER; return arr != null && typeof arr !== "function" && arr.length === arr.length | 0 && arr.length >= minLength && arr.length <= maxLength; }
4+
5+
if (_hasProps(x, "a", "aa") && _hasLength(x.aa, 2) && _hasProps(x.aa[1])) {
6+
const { a, aa: [b, { c = 1 }, ...d] } = x;
7+
8+
d.concat(a + b + c);
9+
}
Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,27 @@
1-
function _hasProps(obj, props) {
2-
return obj != null && (typeof obj === "object" || typeof obj === "function") && props.filter(function (prop) {
3-
return prop in obj;
4-
}).length === props.length;
5-
}
1+
function _hasProps(obj) { if (obj == null) return false; if (typeof obj !== "object" && typeof obj !== "function") return false; var i = arguments.length; while (--i > 0) { if (!(arguments[i] in obj)) return false; } return true; }
62

7-
if (_hasProps(x, ["a"])) {
3+
if (_hasProps(x, "a")) {
84
const { a } = x;
95

106
a;
11-
} else if (_hasProps(x, ["a", "b"])) {
7+
} else if (_hasProps(x, "a", "b")) {
128
const { a, b } = x;
139

1410
a + b;
15-
} else if (_hasProps(x, ["a"])) {
11+
} else if (_hasProps(x, "a")) {
1612
const { a, b = 1 } = x;
1713

1814
a + b;
19-
} else if (_hasProps(x, ["a", "b", "c"]) && _hasProps(x.b, ["ba"]) && _hasProps(x.c, ["ca", "cb"]) && _hasProps(x.c.cb, ["cba"])) {
15+
} else if (_hasProps(x, "a", "b", "c") && _hasProps(x.b, "ba") && _hasProps(x.c, "ca", "cb") && _hasProps(x.c.cb, "cba")) {
2016
const { a, b: { ba, bb = 1 }, c: { ca, cb: { cba } } } = x;
2117

2218
a + ba + bb + ca + cba;
23-
} else if ((x === 1 || x === 2) && _hasProps(x, ["a", "b"]) && _hasProps(x.b, ["c"])) {
19+
} else if ((x === 1 || x === 2) && _hasProps(x, "a", "b") && _hasProps(x.b, "c")) {
2420
const { a, b: { c } } = x;
2521

2622
a + c;
27-
} else if (_hasProps(x, []) && (_hasProps(x.a, ["b"]) && _hasProps(x.a.b, ["c"]) || _hasProps(otherObj, ["b"]) && _hasProps(otherObj.b, ["c"]))) {
23+
} else if (_hasProps(x) && (_hasProps(x.a, "b") && _hasProps(x.a.b, "c") || _hasProps(otherObj, "b") && _hasProps(otherObj.b, "c"))) {
2824
const { a: { b: { c } } = otherObj } = x;
2925

3026
c;
31-
} //TODO: test `| { a, ...b }: b`
27+
} //TODO: test `| { a, ...b }: b`

0 commit comments

Comments
 (0)