zoukankan      html  css  js  c++  java
  • ECMA2623 in detail. Chapter 1. Execution Contexts.

     转载地址http://dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts/

    Introduction

    In this note we will mention execution contexts of ECMAScript and types of executable code related with them.

    Definitions

    Every time when control is transferred to ECMAScript executable code, control is entered anexecution context.

    Execution context (abbreviated form — EC) is the abstract concept used by ECMA-262 specification for typification and differentiation of an executable code.

    The standard does not define accurate structure and kind of EC from the technical implementation viewpoint; it is a question of the ECMAScript-engines implementing the standard.

    Logically, set of active execution contexts forms a stack. The bottom of this stack is always a global context, the top — a current (active) execution context. The stack is modified (pushed/popped) during the entering and exiting various kinds of EC.

    Types of executable code

    With abstract concept of an execution context, the concept of type of an executable code is related. Speaking about code type, it is possible in the certain moments to mean an execution context.

    For examples, we define the stack of execution contexts as an array:

    ECStack = [];

    The stack is pushed every time on entering a function (even if the function is called recursively or as the constructor), and also at built-in eval function work.

    Global code

    This type of code is processed at level Program: i.e. the loaded external .js-file or the local inline-code (inside the <script></script> tags). The global code does not include any parts of a code which are in bodies of functions.

    At initialization (program start), ECStack looks like:

    ECStack = [
      globalContext
    ];

    Function code

    On entering the function code (all kinds of functions), ECStack is pushed with new elements. It is necessary to notice that the code of concrete function does not include codes of the inner functions.

    For example, let’s take the function which calls itself recursively once:

    (function foo(flag) {
      if (flag) {
        return;
      }
      foo(true);
    })(false);

    Then, ECStack is modified as follows:

    // first activation of foo
    ECStack = [
      <foo> functionContext
      globalContext
    ];
     
    // recursive activation of foo
    ECStack = [
      <foo> functionContext – recursively
      <foo> functionContext
      globalContext
    ];

    Every return from a function exits the current execution context and ECStack popped accordingly — consecutively and upside-down — quite natural implementation of a stack. After the work of this code is finished, ECStack again contains only globalContext — until the program end.

    A thrown but not caught exception may also exit one or more execution contexts:

    (function foo() {
      (function bar() {
        throw 'Exit from bar and foo contexts';
      })();
    })();

    Eval code

    Things are more interesting with eval code. In this case, there is a concept of a calling context, i.e. a context from which eval function is called.

    The actions made by eval, such as variable or function definition, influence exactly the callingcontext:

    // influence global context
    eval('var x = 10');
     
    (function foo() {
      // and here, variable "y" is
      // created in the local context
      // of "foo" function
      eval('var y = 20');
    })();
     
    alert(x); // 10
    alert(y); // "y" is not defined

    Note, in the strict-mode of ES5eval already does not influence the calling context, but instead evaluates the code in the local sandbox.

    For the example above we have the following ECStack modifications:

    ECStack = [
      globalContext
    ];
     
    // eval('var x = 10');
    ECStack.push(
      evalContext,
      callingContext: globalContext
    );
     
    // eval exited context
    ECStack.pop();
     
    // foo funciton call
    ECStack.push(<foo> functionContext);
     
    // eval('var y = 20');
    ECStack.push(
      evalContext,
      callingContext: <foo> functionContext
    );
     
    // return from eval
    ECStack.pop();
     
    // return from foo
    ECStack.pop();

    I.e. quite casual and logical call-stack.

    In old SpiderMonkey implementations (Firefox), up to version 1.7, it was possible to pass a calling context as a second argument for eval function. Thus, if the context still exists, it is possible to influence private variables:

    function foo() {
      var x = 1;
      return function () { alert(x); };
    };
     
    var bar = foo();
     
    bar(); // 1
     
    eval('x = 2', bar); // pass context, influence internal var "x"
     
    bar(); // 2

    However, due to security reasons in modern engines it was fixed and is not significant anymore.

    Conclusion

    This theoretical minimum is required for the further analysis of details related with execution contexts, such as variable object or scope chain, which descriptions can be found in the appropriate chapters.

    Additional literature

    Corresponding section of ECMA-262-3 specification — 10. Execution Contexts.

  • 相关阅读:
    并发编程-阻塞队列&JUC常用工具
    并发编程-Condition源码分析&基于Condition实现阻塞队列
    并发编程-ReentrantLock锁源码分析&Condition设计
    并发编程-JMM&ReentrantLock锁以及原理
    数据库操作支持函数
    python内置进制转换函数
    三目运算符
    数据库常见操作
    宏使用汇总
    sort: invalid comparator
  • 原文地址:https://www.cnblogs.com/lwhkdash/p/2344349.html
Copyright © 2011-2022 走看看