Skip to content

Commit 5958fb4

Browse files
Add call tests + Split into multiple files
1 parent a71b67d commit 5958fb4

File tree

4 files changed

+195
-117
lines changed

4 files changed

+195
-117
lines changed

test/es12/optional-calls.js

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
4+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
5+
//-------------------------------------------------------------------------------------------------------
6+
7+
// @ts-check
8+
/// <reference path="../UnitTestFramework/UnitTestFramework.js" />
9+
10+
WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
11+
12+
const simpleObj = { "null": null, "undefined": undefined, something: 42 };
13+
Object.freeze(simpleObj);
14+
15+
const tests = [
16+
{
17+
name: "Simple method call on property",
18+
body() {
19+
// Verify normal behavior
20+
assert.throws(() => simpleObj.nothing(), TypeError);
21+
assert.throws(() => simpleObj.null(), TypeError);
22+
assert.throws(() => simpleObj.undefined(), TypeError);
23+
24+
// With optional-chains
25+
assert.isUndefined(simpleObj.nothing?.(), "OptChain should evaluated to 'undefined'");
26+
assert.isUndefined(simpleObj.null?.(), "OptChain should evaluated to 'undefined'");
27+
assert.isUndefined(simpleObj.undefined?.(), "OptChain should evaluated to 'undefined'");
28+
}
29+
},
30+
{
31+
name: "Simple method call on indexer",
32+
body() {
33+
// Verify normal behavior
34+
assert.throws(() => simpleObj["nothing"](), TypeError);
35+
assert.throws(() => simpleObj["null"](), TypeError);
36+
assert.throws(() => simpleObj["undefined"](), TypeError);
37+
38+
// With optional-chains
39+
assert.isUndefined(simpleObj["nothing"]?.(), "OptChain should evaluated to 'undefined'");
40+
assert.isUndefined(simpleObj["null"]?.(), "OptChain should evaluated to 'undefined'");
41+
assert.isUndefined(simpleObj["undefined"]?.(), "OptChain should evaluated to 'undefined'");
42+
}
43+
},
44+
{
45+
name: "Simple method call on non-callable property",
46+
body() {
47+
// Verify normal behavior
48+
assert.throws(() => simpleObj.something(), TypeError, "Non-callable prop", "Function expected");
49+
50+
// With optional-chains
51+
assert.throws(() => simpleObj.something?.(), TypeError, "Non-callable prop", "Function expected");
52+
assert.throws(() => simpleObj?.something(), TypeError, "Non-callable prop", "Function expected");
53+
assert.throws(() => simpleObj?.something?.(), TypeError, "Non-callable prop", "Function expected");
54+
}
55+
},
56+
{
57+
name: "Simple method call on non-callable indexer",
58+
body() {
59+
// Verify normal behavior
60+
assert.throws(() => simpleObj["something"](), TypeError, "Non-callable prop", "Function expected");
61+
62+
// With optional-chains
63+
assert.throws(() => simpleObj["something"]?.(), TypeError, "Non-callable prop", "Function expected");
64+
assert.throws(() => simpleObj?.["something"](), TypeError, "Non-callable prop", "Function expected");
65+
assert.throws(() => simpleObj?.["something"]?.(), TypeError, "Non-callable prop", "Function expected");
66+
}
67+
},
68+
{
69+
name: "Optional properties before call",
70+
body() {
71+
// Verify normal behavior
72+
assert.throws(() => simpleObj.nothing.something(), TypeError);
73+
assert.throws(() => simpleObj.null.something(), TypeError);
74+
assert.throws(() => simpleObj.undefined.something(), TypeError);
75+
76+
// With optional-chains
77+
assert.isUndefined(simpleObj.nothing?.something(), "OptChain should evaluated to 'undefined'");
78+
assert.isUndefined(simpleObj.null?.something(), "OptChain should evaluated to 'undefined'");
79+
assert.isUndefined(simpleObj.undefined?.something(), "OptChain should evaluated to 'undefined'");
80+
}
81+
},
82+
{
83+
name: "Optional indexers before call",
84+
body() {
85+
// Verify normal behavior
86+
assert.throws(() => simpleObj.nothing["something"](), TypeError);
87+
assert.throws(() => simpleObj.null["something"](), TypeError);
88+
assert.throws(() => simpleObj.undefined["something"](), TypeError);
89+
90+
// With optional-chains
91+
assert.isUndefined(simpleObj.nothing?.["something"](), "OptChain should evaluated to 'undefined'");
92+
assert.isUndefined(simpleObj.null?.["something"](), "OptChain should evaluated to 'undefined'");
93+
assert.isUndefined(simpleObj.undefined?.["something"](), "OptChain should evaluated to 'undefined'");
94+
}
95+
},
96+
{
97+
name: "Propagate 'this' correctly",
98+
body() {
99+
const specialObj = {
100+
b() { return this._b; },
101+
_b: { c: 42 }
102+
};
103+
104+
assert.areEqual(42, specialObj.b().c);
105+
assert.areEqual(42, specialObj?.b().c);
106+
assert.areEqual(42, specialObj.b?.().c);
107+
assert.areEqual(42, specialObj?.b?.().c);
108+
assert.areEqual(42, (specialObj?.b)().c);
109+
assert.areEqual(42, (specialObj.b)?.().c);
110+
assert.areEqual(42, (specialObj?.b)?.().c);
111+
}
112+
}
113+
];
114+
115+
testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });

test/es12/optional-chaining.js

Lines changed: 1 addition & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
1111

12-
const simpleObj = { "null": null, "undefined": undefined };
12+
const simpleObj = { "null": null, "undefined": undefined, something: 42 };
1313
Object.freeze(simpleObj);
1414

1515
const tests = [
@@ -41,48 +41,6 @@ const tests = [
4141
assert.isUndefined(simpleObj.undefined?.["something"], "OptChain should evaluated to 'undefined'");
4242
}
4343
},
44-
{
45-
name: "Simple method calls",
46-
body() {
47-
// Verify normal behavior
48-
assert.throws(() => simpleObj.nothing(), TypeError);
49-
assert.throws(() => simpleObj.null(), TypeError);
50-
assert.throws(() => simpleObj.undefined(), TypeError);
51-
52-
// With optional-chains
53-
assert.isUndefined(simpleObj.nothing?.(), "OptChain should evaluated to 'undefined'");
54-
assert.isUndefined(simpleObj.null?.(), "OptChain should evaluated to 'undefined'");
55-
assert.isUndefined(simpleObj.undefined?.(), "OptChain should evaluated to 'undefined'");
56-
}
57-
},
58-
{
59-
name: "Simple properties before call",
60-
body() {
61-
// Verify normal behavior
62-
assert.throws(() => simpleObj.nothing.something(), TypeError);
63-
assert.throws(() => simpleObj.null.something(), TypeError);
64-
assert.throws(() => simpleObj.undefined.something(), TypeError);
65-
66-
// With optional-chains
67-
assert.isUndefined(simpleObj.nothing?.something(), "OptChain should evaluated to 'undefined'");
68-
assert.isUndefined(simpleObj.null?.something(), "OptChain should evaluated to 'undefined'");
69-
assert.isUndefined(simpleObj.undefined?.something(), "OptChain should evaluated to 'undefined'");
70-
}
71-
},
72-
{
73-
name: "Simple indexers before call",
74-
body() {
75-
// Verify normal behavior
76-
assert.throws(() => simpleObj.nothing["something"], TypeError);
77-
assert.throws(() => simpleObj.null["something"], TypeError);
78-
assert.throws(() => simpleObj.undefined["something"], TypeError);
79-
80-
// With optional-chains
81-
assert.isUndefined(simpleObj.nothing?.["something"](), "OptChain should evaluated to 'undefined'");
82-
assert.isUndefined(simpleObj.null?.["something"](), "OptChain should evaluated to 'undefined'");
83-
assert.isUndefined(simpleObj.undefined?.["something"](), "OptChain should evaluated to 'undefined'");
84-
}
85-
},
8644
{
8745
name: "Short-circuiting ignores indexer expression and method args",
8846
body() {
@@ -137,86 +95,12 @@ const tests = [
13795
assert.areEqual(2, i, "Properties should be called")
13896
}
13997
},
140-
{
141-
name: "Propagate 'this' correctly",
142-
body() {
143-
const specialObj = {
144-
b() { return this._b; },
145-
_b: { c: 42 }
146-
};
147-
148-
assert.areEqual(42, specialObj.b().c);
149-
assert.areEqual(42, specialObj?.b().c);
150-
assert.areEqual(42, specialObj.b?.().c);
151-
assert.areEqual(42, specialObj?.b?.().c);
152-
assert.areEqual(42, (specialObj?.b)().c);
153-
assert.areEqual(42, (specialObj.b)?.().c);
154-
assert.areEqual(42, (specialObj?.b)?.().c);
155-
}
156-
},
15798
// Null check
15899
{
159100
name: "Only check for 'null' and 'undefined'",
160101
body() {
161102
assert.areEqual(0, ""?.length, "Expected empty string length");
162103
}
163-
},
164-
// Parsing
165-
{
166-
name: "Parse ternary correctly",
167-
body() {
168-
assert.areEqual(0.42, eval(`"this is not falsy"?.42 : 0`));
169-
}
170-
},
171-
{
172-
name: "Tagged Template in OptChain is illegal",
173-
body() {
174-
assert.throws(() => eval("simpleObj.undefined?.`template`"), SyntaxError, "No TaggedTemplate here", "Invalid tagged template in optional chain.");
175-
assert.throws(() => eval(`simpleObj.undefined?.
176-
\`template\``), SyntaxError, "No TaggedTemplate here", "Invalid tagged template in optional chain.");
177-
}
178-
},
179-
{
180-
name: "No new in OptChain",
181-
body() {
182-
assert.throws(() => eval(`
183-
class Test { }
184-
new Test?.();
185-
`), SyntaxError, "'new' in OptChain is illegal", "Invalid optional chain in new expression.");
186-
}
187-
},
188-
{
189-
name: "No super in OptChain",
190-
body() {
191-
assert.throws(() => eval(`
192-
class Base { }
193-
class Test extends Base {
194-
constructor(){
195-
super?.();
196-
}
197-
}
198-
`), SyntaxError, "Super in OptChain is illegal", "Invalid use of the 'super' keyword");
199-
200-
assert.throws(() => eval(`
201-
class Base { }
202-
class Test extends Base {
203-
constructor(){
204-
super();
205-
206-
super?.abc;
207-
}
208-
}
209-
`), SyntaxError, "Super in OptChain is illegal", "Invalid use of the 'super' keyword");
210-
}
211-
},
212-
{
213-
name: "No assignment",
214-
body() {
215-
const a = {};
216-
assert.throws(() => eval(`a?.b++`), SyntaxError, "Assignment is illegal", "Invalid left-hand side in assignment.");
217-
assert.throws(() => eval(`a?.b += 1`), SyntaxError, "Assignment is illegal", "Invalid left-hand side in assignment.");
218-
assert.throws(() => eval(`a?.b = 5`), SyntaxError, "Assignment is illegal", "Invalid left-hand side in assignment.");
219-
}
220104
}
221105
];
222106

test/es12/optional-parsing.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
4+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
5+
//-------------------------------------------------------------------------------------------------------
6+
7+
// @ts-check
8+
/// <reference path="../UnitTestFramework/UnitTestFramework.js" />
9+
10+
WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
11+
12+
const tests = [
13+
{
14+
name: "Parse ternary correctly",
15+
body() {
16+
assert.areEqual(0.42, eval(`"this is not falsy"?.42 : 0`));
17+
}
18+
},
19+
{
20+
name: "Tagged Template in OptChain is illegal",
21+
body() {
22+
assert.throws(() => eval("simpleObj.undefined?.`template`"), SyntaxError, "No TaggedTemplate here", "Invalid tagged template in optional chain.");
23+
assert.throws(() => eval(`simpleObj.undefined?.
24+
\`template\``), SyntaxError, "No TaggedTemplate here", "Invalid tagged template in optional chain.");
25+
}
26+
},
27+
{
28+
name: "No new in OptChain",
29+
body() {
30+
assert.throws(() => eval(`
31+
class Test { }
32+
new Test?.();
33+
`), SyntaxError, "'new' in OptChain is illegal", "Invalid optional chain in new expression.");
34+
}
35+
},
36+
{
37+
name: "No super in OptChain",
38+
body() {
39+
assert.throws(() => eval(`
40+
class Base { }
41+
class Test extends Base {
42+
constructor(){
43+
super?.();
44+
}
45+
}
46+
`), SyntaxError, "Super in OptChain is illegal", "Invalid use of the 'super' keyword");
47+
48+
assert.throws(() => eval(`
49+
class Base { }
50+
class Test extends Base {
51+
constructor(){
52+
super();
53+
54+
super?.abc;
55+
}
56+
}
57+
`), SyntaxError, "Super in OptChain is illegal", "Invalid use of the 'super' keyword");
58+
}
59+
},
60+
{
61+
name: "No assignment",
62+
body() {
63+
const a = {};
64+
assert.throws(() => eval(`a?.b++`), SyntaxError, "Assignment is illegal", "Invalid left-hand side in assignment.");
65+
assert.throws(() => eval(`a?.b += 1`), SyntaxError, "Assignment is illegal", "Invalid left-hand side in assignment.");
66+
assert.throws(() => eval(`a?.b = 5`), SyntaxError, "Assignment is illegal", "Invalid left-hand side in assignment.");
67+
}
68+
}
69+
];
70+
71+
testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });

test/es12/rlexe.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,13 @@
55
<files>optional-chaining.js</files>
66
<compile-flags>-args summary -endargs</compile-flags>
77
</default>
8+
<default>
9+
<files>optional-parsing.js</files>
10+
<compile-flags>-args summary -endargs</compile-flags>
11+
</default>
12+
<default>
13+
<files>optional-calls.js</files>
14+
<compile-flags>-args summary -endargs</compile-flags>
15+
</default>
816
</test>
917
</regress-exe>

0 commit comments

Comments
 (0)