in ECMAScript

ECMA-262-3 in detail. Chapter 1. Execution Contexts.

Read this article in: Russian, Chinese, French.

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 an execution 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 = [
  &lt;foo&gt; functionContext
  globalContext
];
 
// recursive activation of foo
ECStack = [
  &lt;foo&gt; functionContext – recursively 
  &lt;foo&gt; 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 calling context:

// 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 ES5, eval 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({
  context: evalContext,
  callingContext: globalContext
});

// eval exited context
ECStack.pop();

// foo funciton call
ECStack.push(&lt;foo&gt; functionContext);

// eval('var y = 20');
ECStack.push({
  context: evalContext,
  callingContext: &lt;foo&gt; 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.

Note: ES2015+ introduced one more code type — module code.

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.


Translated by: Dmitry Soshnikov.
Published on: 2010-03-11

Originally written by: Dmitry Soshnikov [ru, read »]
Originally published on: 2009-06-26

Write a Comment

Comment

36 Comments

  1. Thanks for these excellent articles! Your blog is very professional and useful for every JavaScript programmer.

  2. @justin

    Thanks, justin. As Google translate shows me (unfortunately I can’t read Chinese myself :)), your translation is good. I am glad to see Chinese colleagues interested in deep JavaScript; that’s great.

    I added a link to your translation.

    Dmitry.

  3. Thanks for these series. An excellent overview of the specification.

  4. Thanks, I am trying hard to understand EC, now I know why them call it “Abstract” lol!!

  5. It is a great article. I want to translate to Korean so that other my friends can take it quickly.
    I have a question regarding below:

    “In SpiderMonkey implementation (built into Firefox, Thunderbird), up to version 1.7, it is possible to pass a calling context as a second argument for eval function.”

    I would like to clarify “up to version 1.7”. Did you mean after that version it doesn’t support the feature?

    And also did the version mean JavaScript Version? As far as I know there is 1.8.x version of JavaScript.

    Thanks.

  6. @Hans Höglund, @Alex Bars, thanks!

    @David Lee, thanks,

    I want to translate to Korean

    Yes, great. Please contact me when the translation will be ready, I’ll give a link from this article.

    I would like to clarify “up to version 1.7″. Did you mean after that version it doesn’t support the feature?

    Yes, because it was sort of a hack, it was banned. But you still make test in in older Firefox (2) and Rhino versions.

    And also did the version mean JavaScript Version? As far as I know there is 1.8.x version of JavaScript.

    Yes, exactly. The version of Mozilla’s SpiderMonkey is meant.

  7. Thank you for the translation. I can’t read Russian and it was nice you take the time in giving this to us in English.

    Very helpful.

  8. When is created globalContext in the browser? It is diffrent for EC3 and EC5? Scripts in the browser can load and execute at different times and earlier changes in the global object can be seen later.

  9. @Paul, thanks, glad it’s useful.

    @Michael, global context corresponds to evaluation of the script. Every script tag enters its own global execution context and is treated as separate program. However, all of these scripts are share the same global object.

  10. thanks for the great article. here’s a question: since eval code using a calling context, why the stack push addtional eval context above, while pop only the calling one? what’s the difference?

  11. @James Li

    It seems just not the best notation I chose for eval context pushing (there is a confusion with the real push method of arrays which accepts several parameters). There only one context is pushed — the eval‘s context, and the calling context is just a property:

    ECStack.push({
      context: evalContext,
      caller: globalContext
    });
  12. If there is only one eval context being pushed, then I guess you miss putting the globalContext at the bottom, does it look like

    ECStack.push({
      context: evalContext,
      caller: globalContext
    },
    globalContext
    );

    And one more question, as you said, each script file has its own global context and all script files share another global context which is different from the script one, is it a purely implementation choice?

  13. awesome article~~thanks for your summary on specification~~only one question with your comment

    global context corresponds to evaluation of the script. Every script tag enters its own global execution context and is treated as separate program. However, all of these scripts are share the same global object.

    what is the difference between the global execution context into which scipt tags enter and the global object shared by these scripts?
    hope for your reply~~

  14. Hi,Dmitry A. Soshnikov
    It’s my honor to read your articles.But I have some problems as following.
    For exmaple,how to unstanding the globle code.There is a javascript code.Which’s the global code?Line one?

     
            1.var a = 10;
            2.var b = "Dimtry";
            3.var c = new Object();
            4.var d = { a: 123, b: 'aaa' };
            5.function D() {
                alert("I don't know how to unstanding the global code.");
            }
            6.D();
            7.b = a + b;
        
  15. Thank you for these very informative “ECMA-262-3 in Detail” articles. They have done so much to clear up my confusion on ECMA script.

  16. Hi. Thank you for this gem. This is absolutely brilliant work.

  17. Hi Dmitry

    Thanks for this great series.
    Would you please cover ecmascript6 in deep, just like this series.

    Peace

  18. @TY, thanks, glad it’s useful. Yes, will see about ES6, probably will write some overall articles as JS Core.

  19. Hi @Dmitry,

    This’s best article I have saw about javascript introduction. Thanks your contribution. 🙂

  20. Excellent, clear, concise, and so intelligibly written that my cat was able to finally understand the execution stack in JavaScript. He’s been struggling with that for days. I enjoyed it thoroughly as well.
    Just want to say that you should add this to your CSS:
    `.header-link code {
    font-size: 1em;
    }`
    In the `Eval` Code section, the `code` element inside the header is super tiny compared the second half of the header.
    Thank you for your writings!

  21. @Justin, thanks for the feedback, appreciated, and glad the article is useful. And also thanks for the CSS tips, I do design revisions periodically, will consider making the font bigger.

  22. Thanks for you sharing, I have some questions.

    function foo() {
      var a = 10;
      var b = 20;
      function bar(param) {
       return a + param;
      }
      return bar;
    }
    
    var func = foo();
    func(5);

    Where is variable `a` saved in memory? only stack? both stack and AO?
    Where is AO saved in memory?

    It bothered me a lot.

  23. @GuoMinkgkai, local variables are saved in the local environment (i.e. the activation object). And since it has to support closures semantics, it cannot be stack-allocated, but should be rather heap-allocated.

  24. Hello Dmitry, I’m in year 2019 and studying through your masterpiece written in 2010.
    This article give me a lot of teaching. Really good and I don’t know how to describe my emotion. It blow my mind.
    Here is my question.
    In the title, ECMA-262-3, what does that number meaning? what is 262, and what is 3?
    I already search on the internet but there was no satisfactory results.
    And thank you again your article.

  25. @Dmitry.
    Hi, first let me show my thanks to you for your excellent series of JavaScript lectures and articles。Actually, I’ve been reading your articles times and times since 2014。Every time I’ll learn a lot from your lectures.This may be the fourth time that I learn ECMAScript knowledge.
    I’ll carefully study again this time and try to understand every detail in your article. So can you answer me some questions? For example, in this article it is mentioned that “Every time when control is transferred to ECMAScript executable code, control is entered an execution context” . I want to know more about “controll”: what does it mean? or, what the whole sentence mean?

  26. @Dmitry,

    Hi, would you mind if I ask you another question in this article: what does the word “concrete” mean in the sentence “It is necessary to notice that the code of concrete function does not include codes of the inner functions”?
    I’m looking forward your answer, thanks 🙂

  27. @Jackie zheng, thanks for the feedback, glad the learning materials are useful.

    what does the word “concrete” mean

    A “concrete” function is just wording for “any”, or “specific”.

    Example:

    function foo() {
      function bar() {}
    }
    

    The code of the foo function doesn’t include the code of the bar function.

    I want to know more about “controll”: what does it mean? or, what the whole sentence mean?

    This is control flow. This means whenever we execute (“control is transferred to”) any JS code, always a new execution context is created.

  28. @autumn, thanks for the feedback, glad to see more people interested in deep JS.

    ECMA-262 is the specification for ECMAScript, which is the standardized version of JavaScript.

  29. Hi Dmitry,
    Is the concept of execution context, can connect with the js engine process (compilation and interpretation)?
    Such as , When js engine create execution context? is in compilation ?

  30. Hello, Dmitry. Your articles are just mind blowing.
    I just want to ask :
    Did you also wrote about how module works ??
    Or How module context as you mentioned works ?
    I am not able to find it on your website.

  31. @Jay, thanks for the feedback, yes, I’ll need to add some descriptions about module environments in the future.