Bug 153864 - Invoking super()/super inside of the eval should not lead to SyntaxError
Summary: Invoking super()/super inside of the eval should not lead to SyntaxError
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks: 140491 140855 154027 155491
  Show dependency treegraph
 
Reported: 2016-02-04 03:45 PST by GSkachkov
Modified: 2016-03-17 12:46 PDT (History)
7 users (show)

See Also:


Attachments
Patch (24.63 KB, patch)
2016-03-06 13:01 PST, GSkachkov
no flags Details | Formatted Diff | Diff
Patch (30.79 KB, patch)
2016-03-15 07:14 PDT, GSkachkov
no flags Details | Formatted Diff | Diff
Patch (39.78 KB, patch)
2016-03-16 13:11 PDT, GSkachkov
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description GSkachkov 2016-02-04 03:45:25 PST
Following case should not lead to Syntax Error:
class A {
}
class B extends A {
  constructor() {
    eval("eval('super()')");
  }
}

new B();
Comment 1 GSkachkov 2016-02-07 23:46:31 PST
Following case should not lead to Syntax Error:

const defaultValue = 'default-value';

class A {
  setDefaultValue() {
      this.value = defaultValue;
  }
}

class B extends A {
  constructor() {
    eval("super()");
  }
  setValue () {
      eval("super.setDefaultValue()");
  }
}

let b = new B();
b.setValue();
b.id === defaultValue;
Comment 2 GSkachkov 2016-03-06 13:01:35 PST
Created attachment 273142 [details]
Patch

Patch, more test will be later
Comment 3 Saam Barati 2016-03-07 19:04:13 PST
Comment on attachment 273142 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=273142&action=review

> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h:307
> +            return !(m_codeBlock->isArrowFunction() || m_codeType == EvalCode) || m_isNewTargetLoadedInArrowFunction
>                  ? m_newTargetRegister : emitLoadNewTargetFromArrowFunctionLexicalEnvironment();

This function is getting hard to read. I vote for an if statement here.
Also, I found a bug in the logic of caching here:
https://bugs.webkit.org/show_bug.cgi?id=155153

> Source/JavaScriptCore/parser/Parser.cpp:2068
> +            ConstructorKind functionConstructorKind = functionBodyType == StandardFunctionBodyBlock && !m_isEvalContext

Don't we already know if we're parsing an eval?
Why do we need m_isEvalContext?
Maybe I'm mistaken.

> Source/JavaScriptCore/parser/Parser.cpp:3820
> +        semanticFailIfFalse(currentScope()->isFunction() || (m_isEvalContext && closestParentOrdinaryFunctionNonLexicalScope()->expectedSuperBinding() == SuperBinding::Needed), "super is only valid inside functions");

This error message should be updated.

> Source/JavaScriptCore/runtime/CodeCache.cpp:104
> +    bool isEvalConext = true;

This is definitely not true. This should probably be a parameter to this function.

> Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-superproperty.js:232
> +class K extends A {

let's have some eval tests inside a constructor.
tests for TDZ, etc.
Comment 4 GSkachkov 2016-03-15 07:14:20 PDT
Created attachment 274093 [details]
Patch
Comment 5 GSkachkov 2016-03-15 09:49:56 PDT
Comment on attachment 273142 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=273142&action=review

>> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h:307
>>                  ? m_newTargetRegister : emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
> 
> This function is getting hard to read. I vote for an if statement here.
> Also, I found a bug in the logic of caching here:
> https://bugs.webkit.org/show_bug.cgi?id=155153

OK. It will be overwritten in fix of the 155153

>> Source/JavaScriptCore/parser/Parser.cpp:2068
>> +            ConstructorKind functionConstructorKind = functionBodyType == StandardFunctionBodyBlock && !m_isEvalContext
> 
> Don't we already know if we're parsing an eval?
> Why do we need m_isEvalContext?
> Maybe I'm mistaken.

In new patch,  I've used isEvalNode template function that is deepest place where I can check EvalNode.

>> Source/JavaScriptCore/parser/Parser.cpp:3820
>> +        semanticFailIfFalse(currentScope()->isFunction() || (m_isEvalContext && closestParentOrdinaryFunctionNonLexicalScope()->expectedSuperBinding() == SuperBinding::Needed), "super is only valid inside functions");
> 
> This error message should be updated.

Yeah, I've created issue https://bugs.webkit.org/show_bug.cgi?id=155491. There is several tests that rely on this 'text', so I decided to separate this change is another patch.

>> Source/JavaScriptCore/runtime/CodeCache.cpp:104
>> +    bool isEvalConext = true;
> 
> This is definitely not true. This should probably be a parameter to this function.

Removed

>> Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-superproperty.js:232
>> +class K extends A {
> 
> let's have some eval tests inside a constructor.
> tests for TDZ, etc.

Done
Comment 6 Saam Barati 2016-03-15 20:03:37 PDT
Comment on attachment 274093 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=274093&action=review

> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:643
> +    if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunctionContext() && !isDerivedConstructorContext()) {

Why the "!isDerivedConstructorContext()" check?

> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:4145
> +    return m_scopeNode->doAnyInnerArrowFunctionsUseNewTarget() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();

I believe m_codeBlock->usesEval() should always be true if m_scopeNode->doAnyInnerAroowFunctionsUseEval().
You should double check though.

> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:4150
> +    return m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();

ditto

> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:4155
> +    return m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();

ditto

> Source/JavaScriptCore/parser/Parser.cpp:3848
> +        // TODO: Change error message for more suitable. https://bugs.webkit.org/show_bug.cgi?id=155491 

Style: FIXME not TODO
Comment 7 Saam Barati 2016-03-16 00:57:14 PDT
Comment on attachment 274093 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=274093&action=review

> Source/JavaScriptCore/ChangeLog:3
> +        Invoking super()/super inside of the eval should not lead to SyntaxError

Do we have a bug open for new.target inside eval?

>> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:643
>> +    if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunctionContext() && !isDerivedConstructorContext()) {
> 
> Why the "!isDerivedConstructorContext()" check?

Ah, I guess it's that way so we don't recreate a scope. I think I understand.
Comment 8 GSkachkov 2016-03-16 11:16:54 PDT
Comment on attachment 274093 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=274093&action=review

>> Source/JavaScriptCore/ChangeLog:3
>> +        Invoking super()/super inside of the eval should not lead to SyntaxError
> 
> Do we have a bug open for new.target inside eval?

Yes, I did this recently
 https://bugs.webkit.org/show_bug.cgi?id=155545

>>> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:643
>>> +    if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunctionContext() && !isDerivedConstructorContext()) {
>> 
>> Why the "!isDerivedConstructorContext()" check?
> 
> Ah, I guess it's that way so we don't recreate a scope. I think I understand.

Yes, that is correct. It is for this case: 
class C {};
class D extends C {
  constructor() {
    eval("(()=>super())()");//Error
  }
}
new D();
Otherwise we will have two context scope for 'this'. I've spend last three evenings to find out why mention simple test case did not work

>> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:4145
>> +    return m_scopeNode->doAnyInnerArrowFunctionsUseNewTarget() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
> 
> I believe m_codeBlock->usesEval() should always be true if m_scopeNode->doAnyInnerAroowFunctionsUseEval().
> You should double check though.

It is true, but unfortunately this patch cover cases when we do not have arrow function, for instance from previous comments, so I need to check m_codeBlock->usesEval(). Possible we need to change name of the function isNewTargetUsedInInnerArrowFunction -> isNewTargetUsedInInnerArrowFunctionOrEval

>> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:4150
>> +    return m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
> 
> ditto

The same

>> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:4155
>> +    return m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
> 
> ditto

The same

>> Source/JavaScriptCore/parser/Parser.cpp:3848
>> +        // TODO: Change error message for more suitable. https://bugs.webkit.org/show_bug.cgi?id=155491 
> 
> Style: FIXME not TODO

Will be updated in next patch.
Comment 9 Saam Barati 2016-03-16 11:46:18 PDT
(In reply to comment #8)
> Comment on attachment 274093 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=274093&action=review
> 
> >> Source/JavaScriptCore/ChangeLog:3
> >> +        Invoking super()/super inside of the eval should not lead to SyntaxError
> > 
> > Do we have a bug open for new.target inside eval?
> 
> Yes, I did this recently
>  https://bugs.webkit.org/show_bug.cgi?id=155545
> 
> >>> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:643
> >>> +    if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunctionContext() && !isDerivedConstructorContext()) {
> >> 
> >> Why the "!isDerivedConstructorContext()" check?
> > 
> > Ah, I guess it's that way so we don't recreate a scope. I think I understand.
> 
> Yes, that is correct. It is for this case: 
> class C {};
> class D extends C {
>   constructor() {
>     eval("(()=>super())()");//Error
>   }
> }
> new D();
> Otherwise we will have two context scope for 'this'. I've spend last three
> evenings to find out why mention simple test case did not work
> 
> >> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:4145
> >> +    return m_scopeNode->doAnyInnerArrowFunctionsUseNewTarget() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
> > 
> > I believe m_codeBlock->usesEval() should always be true if m_scopeNode->doAnyInnerAroowFunctionsUseEval().
> > You should double check though.
> 
> It is true, but unfortunately this patch cover cases when we do not have
> arrow function, for instance from previous comments, so I need to check
> m_codeBlock->usesEval(). Possible we need to change name of the function
> isNewTargetUsedInInnerArrowFunction ->
> isNewTargetUsedInInnerArrowFunctionOrEval

What I mean is shouldn't it be sufficient to just check m_codeBlock->usesEval()?
It should never be the case that m_scopeNode->innerArrowEval() is true but m_codeBlock->usesEval() is false.
Therefore, m_codeBlock->usesEval() should cover everything.
Comment 10 GSkachkov 2016-03-16 13:11:35 PDT
Created attachment 274212 [details]
Patch
Comment 11 GSkachkov 2016-03-16 13:31:40 PDT
Comment on attachment 274093 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=274093&action=review

>>>> Source/JavaScriptCore/ChangeLog:3
>>>> +        Invoking super()/super inside of the eval should not lead to SyntaxError
>>> 
>>> Do we have a bug open for new.target inside eval?
>> 
>> Yes, I did this recently
>>  https://bugs.webkit.org/show_bug.cgi?id=155545
> 
> What I mean is shouldn't it be sufficient to just check m_codeBlock->usesEval()?
> It should never be the case that m_scopeNode->innerArrowEval() is true but m_codeBlock->usesEval() is false.
> Therefore, m_codeBlock->usesEval() should cover everything.

Hmm, before it was not, innerArrow... is set only for arrow functions and usesEval only if in current function/block we are using eval. So as for now:
  m_codeBlock->usesEval() is true but m_scopeNode-innerArrowEval() is false for this case -> var f = function () { eval('debug("hello world")'); }; f();
  m_codeBlock->usesEval() is false but m_scopeNode->innerArrowEval() true for case -> var f = function () { var arr = () => () =>  eval('debug("hello world")'); }; f();
Comment 12 GSkachkov 2016-03-17 12:46:09 PDT
Committed r198324: <http://trac.webkit.org/changeset/198324>
Comment 13 GSkachkov 2016-03-17 12:46:25 PDT
All reviewed patches have been landed.  Closing bug.