| // Copyright 2019 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Flags: --allow-natives-syntax |
| |
| var get_count = 0; |
| var has_count = 0; |
| var property_descriptor_count = 0; |
| globalThis.__proto__ = new Proxy({}, |
| {get() {get_count++}, |
| has() {has_count++;}, |
| getOwnPropertyDescriptor() {property_desciptor_count++}}); |
| function checkCounts(count) { |
| assertEquals(has_count, count); |
| assertEquals(get_count, 0); |
| assertEquals(property_descriptor_count, 0); |
| } |
| |
| function load_lookup_global_error() { |
| eval("var b = 10"); |
| x; |
| } |
| assertThrows(load_lookup_global_error, ReferenceError); |
| checkCounts(1); |
| |
| %EnsureFeedbackVectorForFunction(load_lookup_global_error); |
| assertThrows(load_lookup_global_error, ReferenceError); |
| checkCounts(2); |
| assertThrows(load_lookup_global_error, ReferenceError); |
| checkCounts(3); |
| |
| function load_global_error() { |
| x; |
| } |
| assertThrows(load_global_error, ReferenceError); |
| checkCounts(4); |
| |
| %EnsureFeedbackVectorForFunction(load_global_error); |
| assertThrows(load_global_error, ReferenceError); |
| checkCounts(5); |
| assertThrows(load_global_error, ReferenceError); |
| checkCounts(6); |
| |
| |
| // Check when the object is present on the proxy. |
| get_count = 0; |
| has_count = 0; |
| property_descriptor_count = 0; |
| |
| globalThis.__proto__ = new Proxy({}, |
| {get() {get_count++; return 10;}, |
| has() {has_count++; return true;}, |
| getOwnPropertyDescriptor() {property_desciptor_count++}}); |
| function checkCountsWithGet(count) { |
| assertEquals(has_count, count); |
| assertEquals(get_count, count); |
| assertEquals(property_descriptor_count, 0); |
| } |
| |
| function load_lookup_global() { |
| eval("var b = 10"); |
| return x; |
| } |
| assertEquals(load_lookup_global(), 10); |
| checkCountsWithGet(1); |
| |
| %EnsureFeedbackVectorForFunction(load_lookup_global); |
| assertEquals(load_lookup_global(), 10); |
| checkCountsWithGet(2); |
| assertEquals(load_lookup_global(), 10); |
| checkCountsWithGet(3); |
| |
| function load_global() { |
| return x; |
| } |
| assertEquals(load_global(), 10); |
| checkCountsWithGet(4); |
| |
| %EnsureFeedbackVectorForFunction(load_global); |
| assertEquals(load_global(), 10); |
| checkCountsWithGet(5); |
| assertEquals(load_global(), 10); |
| checkCountsWithGet(6); |
| |
| // Check unbound variable access inside typeof |
| get_count = 0; |
| has_count = 0; |
| property_descriptor_count = 0; |
| |
| globalThis.__proto__ = new Proxy({}, |
| {get() {get_count++}, |
| has() {has_count++;}, |
| getOwnPropertyDescriptor() {property_desciptor_count++}}); |
| function checkCountsInsideTypeof(count) { |
| assertEquals(has_count, count); |
| assertEquals(get_count, 0); |
| assertEquals(property_descriptor_count, 0); |
| } |
| |
| function load_lookup_inside_typeof() { |
| eval("var b = 10"); |
| return typeof(x); |
| } |
| assertEquals(load_lookup_inside_typeof(), "undefined"); |
| checkCountsInsideTypeof(1); |
| |
| %EnsureFeedbackVectorForFunction(load_lookup_inside_typeof); |
| assertEquals(load_lookup_inside_typeof(), "undefined"); |
| checkCountsInsideTypeof(2); |
| assertEquals(load_lookup_inside_typeof(), "undefined"); |
| checkCountsInsideTypeof(3); |
| |
| function load_inside_typeof() { |
| return typeof(x); |
| } |
| assertEquals(load_inside_typeof(), "undefined"); |
| checkCountsInsideTypeof(4); |
| |
| %EnsureFeedbackVectorForFunction(load_inside_typeof); |
| assertEquals(load_inside_typeof(), "undefined"); |
| checkCountsInsideTypeof(5); |
| assertEquals(load_inside_typeof(), "undefined"); |
| checkCountsInsideTypeof(6); |
| |
| // Check bound variable access inside typeof |
| get_count = 0; |
| has_count = 0; |
| property_descriptor_count = 0; |
| |
| globalThis.__proto__ = new Proxy({}, |
| {get() {get_count++; return 10;}, |
| has() {has_count++; return true;}, |
| getOwnPropertyDescriptor() {property_desciptor_count++}}); |
| |
| function checkCountsBoundVarInsideTypeof(count) { |
| assertEquals(has_count, count); |
| assertEquals(get_count, count); |
| assertEquals(property_descriptor_count, 0); |
| } |
| |
| function load_lookup_number_inside_typeof() { |
| eval("var b = 10"); |
| return typeof(x); |
| } |
| assertEquals(load_lookup_number_inside_typeof(), "number"); |
| checkCountsBoundVarInsideTypeof(1); |
| |
| %EnsureFeedbackVectorForFunction(load_lookup_number_inside_typeof); |
| assertEquals(load_lookup_number_inside_typeof(), "number"); |
| checkCountsBoundVarInsideTypeof(2); |
| assertEquals(load_lookup_number_inside_typeof(), "number"); |
| checkCountsBoundVarInsideTypeof(3); |
| |
| function load_number_inside_typeof() { |
| return typeof(x); |
| } |
| assertEquals(load_number_inside_typeof(), "number"); |
| checkCountsBoundVarInsideTypeof(4); |
| |
| %EnsureFeedbackVectorForFunction(load_inside_typeof); |
| assertEquals(load_number_inside_typeof(), "number"); |
| checkCountsBoundVarInsideTypeof(5); |
| assertEquals(load_number_inside_typeof(), "number"); |
| checkCountsBoundVarInsideTypeof(6); |
| |
| // Check that if has property returns true we don't throw even when get property |
| // says otherwise. |
| |
| globalThis.__proto__ = new Proxy({}, |
| {has() {has_count++; return true;}, |
| getOwnPropertyDescriptor() {property_desciptor_count++}}); |
| |
| function load_lookup_global_has_property() { |
| eval("var b = 10"); |
| return x; |
| } |
| assertEquals(load_lookup_global_has_property(), undefined); |
| |
| function load_global_has_property() { |
| return x; |
| } |
| assertEquals(load_global_has_property(), undefined); |