michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: /** michael@0: File Name: 12.10-1.js michael@0: ECMA Section: 12.10 The with statement michael@0: Description: michael@0: WithStatement : michael@0: with ( Expression ) Statement michael@0: michael@0: The with statement adds a computed object to the front of the scope chain michael@0: of the current execution context, then executes a statement with this michael@0: augmented scope chain, then restores the scope chain. michael@0: michael@0: Semantics michael@0: michael@0: The production WithStatement : with ( Expression ) Statement is evaluated michael@0: as follows: michael@0: 1. Evaluate Expression. michael@0: 2. Call GetValue(Result(1)). michael@0: 3. Call ToObject(Result(2)). michael@0: 4. Add Result(3) to the front of the scope chain. michael@0: 5. Evaluate Statement using the augmented scope chain from step 4. michael@0: 6. Remove Result(3) from the front of the scope chain. michael@0: 7. Return Result(5). michael@0: michael@0: Discussion michael@0: Note that no matter how control leaves the embedded Statement, whether michael@0: normally or by some form of abrupt completion, the scope chain is always michael@0: restored to its former state. michael@0: michael@0: Author: christine@netscape.com michael@0: Date: 12 november 1997 michael@0: */ michael@0: michael@0: var SECTION = "12.10-1"; michael@0: var VERSION = "ECMA_1"; michael@0: startTest(); michael@0: var TITLE = "The with statement"; michael@0: michael@0: writeHeaderToLog( SECTION + " "+ TITLE); michael@0: michael@0: michael@0: // although the scope chain changes, the this value is immutable for a given michael@0: // execution context. michael@0: michael@0: new TestCase( SECTION, michael@0: "with( new Number() ) { this +'' }", michael@0: GLOBAL, michael@0: eval("with( new Number() ) { this +'' }") ); michael@0: michael@0: // the object's functions and properties should override those of the michael@0: // global object. michael@0: michael@0: new TestCase( michael@0: SECTION, michael@0: "var MYOB = new WithObject(true); with (MYOB) { parseInt() }", michael@0: true, michael@0: eval("var MYOB = new WithObject(true); with (MYOB) { parseInt() }") ); michael@0: michael@0: new TestCase( michael@0: SECTION, michael@0: "var MYOB = new WithObject(false); with (MYOB) { NaN }", michael@0: false, michael@0: eval("var MYOB = new WithObject(false); with (MYOB) { NaN }") ); michael@0: michael@0: new TestCase( michael@0: SECTION, michael@0: "var MYOB = new WithObject(NaN); with (MYOB) { Infinity }", michael@0: Number.NaN, michael@0: eval("var MYOB = new WithObject(NaN); with (MYOB) { Infinity }") ); michael@0: michael@0: new TestCase( michael@0: SECTION, michael@0: "var MYOB = new WithObject(false); with (MYOB) { }; Infinity", michael@0: Number.POSITIVE_INFINITY, michael@0: eval("var MYOB = new WithObject(false); with (MYOB) { }; Infinity") ); michael@0: michael@0: michael@0: new TestCase( michael@0: SECTION, michael@0: "var MYOB = new WithObject(0); with (MYOB) { delete Infinity; Infinity }", michael@0: Number.POSITIVE_INFINITY, michael@0: eval("var MYOB = new WithObject(0); with (MYOB) { delete Infinity; Infinity }") ); michael@0: michael@0: // let us leave the with block via a break. michael@0: michael@0: new TestCase( michael@0: SECTION, michael@0: "var MYOB = new WithObject(0); while (true) { with (MYOB) { Infinity; break; } } Infinity", michael@0: Number.POSITIVE_INFINITY, michael@0: eval("var MYOB = new WithObject(0); while (true) { with (MYOB) { Infinity; break; } } Infinity") ); michael@0: michael@0: michael@0: test(); michael@0: michael@0: function WithObject( value ) { michael@0: this.prop1 = 1; michael@0: this.prop2 = new Boolean(true); michael@0: this.prop3 = "a string"; michael@0: this.value = value; michael@0: michael@0: // now we will override global functions michael@0: michael@0: this.parseInt = new Function( "return this.value" ); michael@0: this.NaN = value; michael@0: this.Infinity = value; michael@0: this.unescape = new Function( "return this.value" ); michael@0: this.escape = new Function( "return this.value" ); michael@0: this.eval = new Function( "return this.value" ); michael@0: this.parseFloat = new Function( "return this.value" ); michael@0: this.isNaN = new Function( "return this.value" ); michael@0: this.isFinite = new Function( "return this.value" ); michael@0: }