[Webkit-unassigned] [Bug 163208] [ES6]. Implement Annex B.3.3 function hoisting rules for eval

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Wed Jan 11 01:57:44 PST 2017


https://bugs.webkit.org/show_bug.cgi?id=163208

--- Comment #22 from Saam Barati <sbarati at apple.com> ---
Comment on attachment 297742
  --> https://bugs.webkit.org/attachment.cgi?id=297742
Patch

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

This code mostly LGTM, some comments below.

Also, it's worth opening a bugzilla for a bug that has existed since I implemented the first version of sloppy hoisting:
function foo() {
    {
         let bar;
         {
              function bar() { }
          }
    }
    return bar;
}
in jsc: foo() === function bar() { }
expected behavior: foo(); throws a ReferenceError
I believe your eval code exhibits the same bad behavior for local lexical variables in the eval.

> Source/JavaScriptCore/bytecode/CodeBlock.cpp:2822
> +        // Fixme: https://bugs.webkit.org/show_bug.cgi?id=166418

Style: "Fixme" => "FIXME"

> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:2186
> +RegisterID* BytecodeGenerator::emitResolveOuterScope(RegisterID* dst, const Identifier& property)

Nit: Lets call this: "emitResolveOuterVarScope"

> Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:2198
> +RegisterID* BytecodeGenerator::emitCheckIfScopeVarType(RegisterID* dst, RegisterID* scope)

Nit: Lets call this: "emitCheckIfScopeIsVarType"

> Source/JavaScriptCore/jit/JITPropertyAccess.cpp:829
> +void JIT::emitSlow_op_is_scope_var_type(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
> +{
> +    linkSlowCase(iter);
> +    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_is_scope_var_type);
> +    slowPathCall.call();
> +}
> +
> +void JIT::emitSlow_op_resolve_closest_var_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
> +{
> +    linkSlowCase(iter);
> +    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_resolve_closest_var_scope);
> +    slowPathCall.call();
> +}

These shouldn't be slow paths. The opcodes should just do the call on the fast patch, and should not have slow paths.

> Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm:2124
> +_llint_op_resolve_closest_var_scope:
> +    traceExecution()
> +    callOpcodeSlowPath(_slow_path_resolve_closest_var_scope)
> +    dispatch(4)
> +
> +_llint_op_is_scope_var_type:
> +    traceExecution()
> +    callOpcodeSlowPath(_slow_path_is_scope_var_type)
> +    dispatch(3)

The 32 and 64 implementations are the same, so they can just go inside LowLevelInterpreter.asm

> Source/JavaScriptCore/parser/Parser.h:639
> +                    addResult.iterator->value.setIsFunction();

Why is this change needed?

> Source/JavaScriptCore/runtime/CommonSlowPaths.cpp:834
> +    bool result = false;
> +    if (scope->isGlobalObject())
> +        result = true;
> +    else if (SymbolTable* scopeSymbolTable = scope->symbolTable())
> +        result = scopeSymbolTable->scopeType() == SymbolTable::ScopeType::VarScope;

This doesn't match the code inside DFGOperations. Which code is correct?

> Source/JavaScriptCore/runtime/JSScope.cpp:234
> +                if (object->hasProperty(exec, ident))
> +                    return object;

I think you need to check an exception here.

> Source/JavaScriptCore/runtime/JSScope.cpp:242
> +        if (object->hasProperty(exec, ident)) {

ditto

> JSTests/stress/eval-func-decl-within-eval-with-reassign-to-var.js:14
> +function foo() {
> +    {
> +        var f = 20;
> +        eval('var f = 15; eval(" { function f() { }; } ")');
> +        assert(typeof f, "function");
> +    }
> +    assert(typeof f, "function", "#1");
> +}

Another good test to have:
function foo() {
    eval("if (false) { function bar() { } }");
    assert(bar === undefined);
}

> JSTests/stress/eval-func-decl-within-eval-with-reassign-to-var.js:56
> +/* //TODO: Set error 
> +// Fixme: Current test does not work because it should raise exception that f could 
> +// not be redeclared
> +function goo() {
> +    {   
> +        var error = false;
> +        try {
> +            let f = 20;
> +            eval('var f = 15; eval(" { function f() { }; } ")');
> +        } catch (e) {
> +            error = e instanceof SyntaxError;
> +        }
> +        assert(error, true, "syntax error should be raisen");
> +    }
> +    assert(typeof f, "undefined", "#6");
> +}
> +
> +for (var i = 0; i < 10000; i++) {
> +    goo();
> +    assert(typeof f, "undefined", "#7");
> +}
> +*/

What's happening with this?

> JSTests/stress/eval-func-decl-within-eval-with-reassign-to-var.js:65
> +function hoo() {
> +    {
> +        let h = 20;
> +        eval('var h = 15; eval(" if (false){ function h() { }; } ");');
> +        assert(h, 15);
> +    }
> +    assert(typeof h, "undefined", "#8");
> +}

Another good test:
function foo() { let h = 20; eval("var h; if (false) { function h() { } }");  return h; }
assert(foo() === 20);

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.webkit.org/pipermail/webkit-unassigned/attachments/20170111/512e2b65/attachment.html>


More information about the webkit-unassigned mailing list