Home | History | Annotate | Download | only in strong
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Flags: --strong-mode --harmony-reflect
      6 // Flags: --allow-natives-syntax
      7 
      8 'use strict';
      9 
     10 
     11 function generateArguments(n, prefix) {
     12   let a = [];
     13   if (prefix) {
     14     a.push(prefix);
     15   }
     16   for (let i = 0; i < n; i++) {
     17     a.push(String(i));
     18   }
     19 
     20   return a.join(', ');
     21 }
     22 
     23 
     24 function generateParams(n, directive_in_body) {
     25   let a = [];
     26   for (let i = 0; i < n; i++) {
     27     a[i] = `p${i}`;
     28   }
     29   return a.join(', ');
     30 }
     31 
     32 function generateParamsWithRest(n, directive_in_body) {
     33   let a = [];
     34   let i = 0;
     35   for (; i < n; i++) {
     36     a[i] = `p${i}`;
     37   }
     38   if (!directive_in_body) {
     39     // If language mode directive occurs in body, rest parameters will trigger
     40     // an early error regardless of language mode.
     41     a.push(`...p${i}`);
     42   }
     43   return a.join(', ');
     44 }
     45 
     46 
     47 function generateSpread(n) {
     48   return `...[${generateArguments(n)}]`;
     49 }
     50 
     51 
     52 (function FunctionCall() {
     53   for (let parameterCount = 0; parameterCount < 3; parameterCount++) {
     54     let defs = [
     55       `'use strong'; function f(${generateParams(parameterCount)}) {}`,
     56       `'use strong'; function f(${generateParamsWithRest(parameterCount)}) {}`,
     57       `'use strong'; function* f(${generateParams(parameterCount)}) {}`,
     58       `'use strong'; function* f(${generateParamsWithRest(parameterCount)}) {}`,
     59       `'use strong'; let f = (${generateParams(parameterCount)}) => {}`,
     60       `function f(${generateParams(parameterCount)}) { 'use strong'; }`,
     61       `function* f(${generateParams(parameterCount)}) { 'use strong'; }`,
     62       `let f = (${generateParams(parameterCount)}) => { 'use strong'; }`,
     63     ];
     64     for (let def of defs) {
     65       for (let argumentCount = 0; argumentCount < 3; argumentCount++) {
     66         let calls = [
     67           `f(${generateArguments(argumentCount)})`,
     68           `f(${generateSpread(argumentCount)})`,
     69           `f.call(${generateArguments(argumentCount, 'undefined')})`,
     70           `f.call(undefined, ${generateSpread(argumentCount)})`,
     71           `f.apply(undefined, [${generateArguments(argumentCount)}])`,
     72           `f.bind(undefined)(${generateArguments(argumentCount)})`,
     73           `%_Call(f, ${generateArguments(argumentCount, 'undefined')})`,
     74           `%Call(f, ${generateArguments(argumentCount, 'undefined')})`,
     75           `%Apply(f, undefined, [${generateArguments(argumentCount)}], 0,
     76                   ${argumentCount})`,
     77         ];
     78 
     79         for (let call of calls) {
     80           let code = `'use strict'; ${def}; ${call};`;
     81           if (argumentCount < parameterCount) {
     82             print(code);
     83             assertThrows(code, TypeError);
     84           } else {
     85             assertDoesNotThrow(code);
     86           }
     87         }
     88       }
     89 
     90       let calls = [
     91         `f.call()`,
     92         `f.apply()`,
     93         `f.apply(undefined)`,
     94       ];
     95       for (let call of calls) {
     96         let code = `'use strict'; ${def}; ${call};`;
     97         if (parameterCount > 0) {
     98           assertThrows(code, TypeError);
     99         } else {
    100           assertDoesNotThrow(code);
    101         }
    102       }
    103     }
    104   }
    105 })();
    106 
    107 
    108 (function MethodCall() {
    109   for (let genParams of [generateParams, generateParamsWithRest]) {
    110     for (let parameterCount = 0; parameterCount < 3; parameterCount++) {
    111       let defs = [
    112         `let o = new class {
    113           m(${genParams(parameterCount, true)}) { 'use strong'; }
    114         }`,
    115         `let o = new class {
    116           *m(${genParams(parameterCount, true)}) { 'use strong'; }
    117         }`,
    118         `let o = { m(${genParams(parameterCount, true)}) { 'use strong'; } }`,
    119         `let o = { *m(${genParams(parameterCount, true)}) { 'use strong'; } }`,
    120         `'use strong';
    121         let o = new class { m(${genParams(parameterCount)}) {} }`,
    122         `'use strong';
    123         let o = new class { *m(${genParams(parameterCount)}) {} }`,
    124         `'use strong'; let o = { m(${genParams(parameterCount)}) {} }`,
    125         `'use strong'; let o = { *m(${genParams(parameterCount)}) {} }`,
    126       ];
    127       for (let def of defs) {
    128         for (let argumentCount = 0; argumentCount < 3; argumentCount++) {
    129           let calls = [
    130             `o.m(${generateArguments(argumentCount)})`,
    131             `o.m(${generateSpread(argumentCount)})`,
    132             `o.m.call(${generateArguments(argumentCount, 'o')})`,
    133             `o.m.call(o, ${generateSpread(argumentCount)})`,
    134             `o.m.apply(o, [${generateArguments(argumentCount)}])`,
    135             `o.m.bind(o)(${generateArguments(argumentCount)})`,
    136             `%_Call(o.m, ${generateArguments(argumentCount, 'o')})`,
    137             `%Call(o.m, ${generateArguments(argumentCount, 'o')})`,
    138             `%Apply(o.m, o, [${generateArguments(argumentCount)}], 0,
    139                     ${argumentCount})`,
    140           ];
    141 
    142           for (let call of calls) {
    143             let code = `'use strict'; ${def}; ${call};`;
    144             if (argumentCount < parameterCount) {
    145               assertThrows(code, TypeError);
    146             } else {
    147               assertDoesNotThrow(code);
    148             }
    149           }
    150         }
    151 
    152         let calls = [
    153           `o.m.call()`,
    154           `o.m.apply()`,
    155           `o.m.apply(o)`,
    156         ];
    157         for (let call of calls) {
    158           let code = `'use strict'; ${def}; ${call};`;
    159           if (parameterCount > 0) {
    160             assertThrows(code, TypeError);
    161           } else {
    162             assertDoesNotThrow(code);
    163           }
    164         }
    165       }
    166     }
    167   }
    168 })();
    169 
    170 
    171 (function Constructor() {
    172   for (let genParams of [generateParams, generateParamsWithRest]) {
    173     for (let argumentCount = 0; argumentCount < 3; argumentCount++) {
    174       for (let parameterCount = 0; parameterCount < 3; parameterCount++) {
    175         let defs = [
    176           `'use strong';
    177           class C { constructor(${genParams(parameterCount)}) {} }`,
    178         ];
    179         for (let def of defs) {
    180           let calls = [
    181             `new C(${generateArguments(argumentCount)})`,
    182             `new C(${generateSpread(argumentCount)})`,
    183             `Reflect.construct(C, [${generateArguments(argumentCount)}])`,
    184           ];
    185           for (let call of calls) {
    186             let code = `${def}; ${call};`;
    187             if (argumentCount < parameterCount) {
    188               assertThrows(code, TypeError);
    189             } else {
    190               assertDoesNotThrow(code);
    191             }
    192           }
    193         }
    194       }
    195     }
    196   }
    197 })();
    198 
    199 
    200 (function DerivedConstructor() {
    201   for (let genParams of [generateParams, generateParamsWithRest]) {
    202     for (let genArgs of [generateArguments, generateSpread]) {
    203       for (let argumentCount = 0; argumentCount < 3; argumentCount++) {
    204         for (let parameterCount = 0; parameterCount < 3; parameterCount++) {
    205           let defs = [
    206             `'use strong';
    207             class B {
    208               constructor(${genParams(parameterCount)}) {}
    209             }
    210             class C extends B {
    211               constructor() {
    212                 super(${genArgs(argumentCount)});
    213               }
    214             }`,
    215           ];
    216           for (let def of defs) {
    217             let code = `${def}; new C();`;
    218             if (argumentCount < parameterCount) {
    219               assertThrows(code, TypeError);
    220             } else {
    221               assertDoesNotThrow(code);
    222             }
    223           }
    224         }
    225       }
    226     }
    227   }
    228 })();
    229 
    230 
    231 (function DerivedConstructorDefaultConstructorInDerivedClass() {
    232   for (let genParams of [generateParams, generateParamsWithRest]) {
    233     for (let genArgs of [generateArguments, generateSpread]) {
    234       for (let argumentCount = 0; argumentCount < 3; argumentCount++) {
    235         for (let parameterCount = 0; parameterCount < 3; parameterCount++) {
    236           let defs = [
    237             `'use strong';
    238             class B {
    239               constructor(${genParams(parameterCount)}) {}
    240             }
    241             class C extends B {}`,
    242           ];
    243           for (let def of defs) {
    244             let code = `${def}; new C(${genArgs(argumentCount)})`;
    245             if (argumentCount < parameterCount) {
    246               assertThrows(code, TypeError);
    247             } else {
    248               assertDoesNotThrow(code);
    249             }
    250           }
    251         }
    252       }
    253     }
    254   }
    255 })();
    256 
    257 
    258 (function TestOptimized() {
    259   function f(x, y) { 'use strong'; }
    260 
    261   assertThrows(f, TypeError);
    262   %OptimizeFunctionOnNextCall(f);
    263   assertThrows(f, TypeError);
    264 
    265   function g() {
    266     f(1);
    267   }
    268   assertThrows(g, TypeError);
    269   %OptimizeFunctionOnNextCall(g);
    270   assertThrows(g, TypeError);
    271 
    272   f(1, 2);
    273   %OptimizeFunctionOnNextCall(f);
    274   f(1, 2);
    275 })();
    276 
    277 
    278 (function TestOptimized2() {
    279   'use strong';
    280   function f(x, y) {}
    281 
    282   assertThrows(f, TypeError);
    283   %OptimizeFunctionOnNextCall(f);
    284   assertThrows(f, TypeError);
    285 
    286   function g() {
    287     f(1);
    288   }
    289   assertThrows(g, TypeError);
    290   %OptimizeFunctionOnNextCall(g);
    291   assertThrows(g, TypeError);
    292 
    293   f(1, 2);
    294   %OptimizeFunctionOnNextCall(f);
    295   f(1, 2);
    296 })();
    297 
    298 
    299 (function TestOptimized3() {
    300   function f(x, y) {}
    301   function g() {
    302     'use strong';
    303     f(1);
    304   }
    305 
    306   g();
    307   %OptimizeFunctionOnNextCall(f);
    308   g();
    309 })();
    310 
    311 
    312 (function ParametersSuper() {
    313   for (let genArgs of [generateArguments, generateSpread]) {
    314     for (let argumentCount = 0; argumentCount < 3; argumentCount++) {
    315       for (let parameterCount = 0; parameterCount < 3; parameterCount++) {
    316         let defs = [
    317           `'use strict';
    318           class B {
    319             m(${generateParams(parameterCount)} ){ 'use strong' }
    320           }`,
    321           `'use strong'; class B { m(${generateParams(parameterCount)}) {} }`,
    322         ];
    323         for (let def of defs) {
    324           let code = `${def};
    325               class D extends B {
    326                 m() {
    327                   super.m(${genArgs(argumentCount)});
    328                 }
    329               }
    330               new D().m()`;
    331           print('\n\n' + code);
    332           if (argumentCount < parameterCount) {
    333             assertThrows(code, TypeError);
    334           } else {
    335             assertDoesNotThrow(code);
    336           }
    337         }
    338       }
    339     }
    340   }
    341 })();
    342