From 49fdae32cb727caebc2ef3ab4ca5b0d0ee964b70 Mon Sep 17 00:00:00 2001 From: Suwei Chen Date: Thu, 9 Jun 2016 10:30:57 -0700 Subject: [PATCH] Enable ES6hasInstance in experimental Recuperate perf loss from existing ES6hasInstance implementation. Perf-neutral with vs. without -es6hasinstance switch. Add inline-cache-invalidation for user-defined Symbol.hasInstance property in function constructor. Revamp unit tests for ES6hasInstance. Related ECMA262 spec sections: 6.1.5.1 Well-Known Symbols 7.3.19 OrdinaryHasInstance (C, O) 12.10.4 Runtime Semantics: InstanceofOperator(O, C) 19.2.3.6 Function.prototype [ @@hasInstance ] ( V ) --- lib/Common/ConfigFlagsList.h | 2 +- lib/Runtime/Language/JavascriptOperators.cpp | 3 +- lib/Runtime/Library/JavascriptFunction.cpp | 16 +- lib/Runtime/Library/JavascriptLibrary.cpp | 1 + test/es6/es6HasInstance.baseline | 19 - test/es6/es6HasInstance.js | 458 ++++++++++++++++--- test/es6/rlexe.xml | 3 +- 7 files changed, 395 insertions(+), 107 deletions(-) delete mode 100644 test/es6/es6HasInstance.baseline diff --git a/lib/Common/ConfigFlagsList.h b/lib/Common/ConfigFlagsList.h index c87968ab1ca..17ceefd4db4 100644 --- a/lib/Common/ConfigFlagsList.h +++ b/lib/Common/ConfigFlagsList.h @@ -900,7 +900,7 @@ FLAGPR (Boolean, ES6, ES6Unscopables , "Enable ES6 With Statem FLAGPR (Boolean, ES6, ES6RegExSticky , "Enable ES6 RegEx sticky flag" , DEFAULT_CONFIG_ES6RegExSticky) FLAGPR_REGOVR_EXP(Boolean, ES6, ES6RegExPrototypeProperties, "Enable ES6 properties on the RegEx prototype" , DEFAULT_CONFIG_ES6RegExPrototypeProperties) FLAGPR_REGOVR_EXP(Boolean, ES6, ES6RegExSymbols , "Enable ES6 RegExp symbols" , DEFAULT_CONFIG_ES6RegExSymbols) -FLAGPR (Boolean, ES6, ES6HasInstance , "Enable ES6 @@hasInstance symbol" , DEFAULT_CONFIG_ES6HasInstanceOf) +FLAGPR_REGOVR_EXP(Boolean, ES6, ES6HasInstance , "Enable ES6 @@hasInstance symbol" , DEFAULT_CONFIG_ES6HasInstanceOf) FLAGPR (Boolean, ES6, ES6Verbose , "Enable ES6 verbose trace" , DEFAULT_CONFIG_ES6Verbose) FLAGPR_REGOVR_EXP(Boolean, ES6, ArrayBufferTransfer , "Enable ArrayBuffer.transfer" , DEFAULT_CONFIG_ArrayBufferTransfer) // /ES6 (BLUE+1) features/flags diff --git a/lib/Runtime/Language/JavascriptOperators.cpp b/lib/Runtime/Language/JavascriptOperators.cpp index 9e1ca9c45de..513bb5eb295 100644 --- a/lib/Runtime/Language/JavascriptOperators.cpp +++ b/lib/Runtime/Language/JavascriptOperators.cpp @@ -6998,7 +6998,8 @@ namespace Js if (scriptContext->GetConfig()->IsES6HasInstanceEnabled()) { Var instOfHandler = JavascriptOperators::GetProperty(constructor, PropertyIds::_symbolHasInstance, scriptContext); - if (JavascriptOperators::IsUndefinedObject(instOfHandler)) + if (JavascriptOperators::IsUndefinedObject(instOfHandler) + || instOfHandler == scriptContext->GetBuiltInLibraryFunction(JavascriptFunction::EntryInfo::SymbolHasInstance.GetOriginalEntryPoint())) { return JavascriptBoolean::ToVar(constructor->HasInstance(instance, scriptContext, inlineCache), scriptContext); } diff --git a/lib/Runtime/Library/JavascriptFunction.cpp b/lib/Runtime/Library/JavascriptFunction.cpp index 8fa725c4057..c7dbb6bf231 100644 --- a/lib/Runtime/Library/JavascriptFunction.cpp +++ b/lib/Runtime/Library/JavascriptFunction.cpp @@ -2697,7 +2697,7 @@ namespace Js BOOL result = DynamicObject::SetProperty(propertyId, value, flags, info); - if (propertyId == PropertyIds::prototype) + if (propertyId == PropertyIds::prototype || propertyId == PropertyIds::_symbolHasInstance) { PropertyValueInfo::SetNoCache(info, this); InvalidateConstructorCacheOnPrototypeChange(); @@ -2711,7 +2711,7 @@ namespace Js { BOOL result = __super::SetPropertyWithAttributes(propertyId, value, attributes, info, flags, possibleSideEffects); - if (propertyId == PropertyIds::prototype) + if (propertyId == PropertyIds::prototype || propertyId == PropertyIds::_symbolHasInstance) { PropertyValueInfo::SetNoCache(info, this); InvalidateConstructorCacheOnPrototypeChange(); @@ -2759,7 +2759,7 @@ namespace Js BOOL result = DynamicObject::DeleteProperty(propertyId, flags); - if (result && propertyId == PropertyIds::prototype) + if (result && propertyId == PropertyIds::prototype || propertyId == PropertyIds::_symbolHasInstance) { InvalidateConstructorCacheOnPrototypeChange(); this->GetScriptContext()->GetThreadContext()->InvalidateIsInstInlineCachesForFunction(this); @@ -2976,18 +2976,14 @@ namespace Js Assert(!(callInfo.Flags & CallFlags_New)); - if (args.Info.Count < 2) - { - JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedObject, _u("Function[Symbol.hasInstance]")); - } - RecyclableObject * constructor = RecyclableObject::FromVar(args[0]); - Var instance = args[1]; - if (!JavascriptConversion::IsCallable(constructor)) + if (!JavascriptConversion::IsCallable(constructor) || args.Info.Count < 2) { return JavascriptBoolean::ToVar(FALSE, scriptContext); } + Var instance = args[1]; + Assert(JavascriptProxy::Is(constructor) || JavascriptFunction::Is(constructor)); return JavascriptBoolean::ToVar(constructor->HasInstance(instance, scriptContext, NULL), scriptContext); } diff --git a/lib/Runtime/Library/JavascriptLibrary.cpp b/lib/Runtime/Library/JavascriptLibrary.cpp index 445893e0885..d13ad6abb60 100644 --- a/lib/Runtime/Library/JavascriptLibrary.cpp +++ b/lib/Runtime/Library/JavascriptLibrary.cpp @@ -2547,6 +2547,7 @@ namespace Js library->AddFunctionToLibraryObjectWithName(functionPrototype, PropertyIds::_symbolHasInstance, PropertyIds::_RuntimeFunctionNameId_hasInstance, &JavascriptFunction::EntryInfo::SymbolHasInstance, 1)); functionPrototype->SetWritable(PropertyIds::_symbolHasInstance, false); + functionPrototype->SetConfigurable(PropertyIds::_symbolHasInstance, false); } DebugOnly(CheckRegisteredBuiltIns(builtinFuncs, scriptContext)); diff --git a/test/es6/es6HasInstance.baseline b/test/es6/es6HasInstance.baseline deleted file mode 100644 index 991c55f8d14..00000000000 --- a/test/es6/es6HasInstance.baseline +++ /dev/null @@ -1,19 +0,0 @@ -*** test1 -checked Symbol.hasInstance -true -*** test2 -checked Symbol.hasInstance -true -checked Symbol.hasInstance -true -*** test3 -Symbol(Symbol.hasInstance) -checked Symbol.hasInstance -false -*** test4 -bind -length -name -Symbol(Symbol.hasInstance) -checked Symbol.hasInstance -false diff --git a/test/es6/es6HasInstance.js b/test/es6/es6HasInstance.js index 1c9c240ef3f..a2a1062d903 100644 --- a/test/es6/es6HasInstance.js +++ b/test/es6/es6HasInstance.js @@ -3,86 +3,396 @@ // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- +// ES6 Function unit tests -// normal function -function test1() { - print('*** test1'); - var o = function (a, b) { - this.x = a; - this.y = b; - } - Object.defineProperty(o, Symbol.hasInstance, { - value: function () { - print('checked Symbol.hasInstance'); - return true; +WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js"); + +var tests = [ + { + name: "change Symbol.hasInstance property of a normal function constructor", + body: function() { + var F = function (a, b) { + this.x = a; + this.y = b; + } + var checked = 0; + + Object.defineProperty(F, Symbol.hasInstance, { + value: function () { + checked++; + return true; + } + }); + + assert.areEqual(true, undefined instanceof F, "undefined instanceof F"); + assert.areEqual(1, checked, "Symbol.hasInstance in a normal function contructor - checked==1"); + assert.areEqual(true, null instanceof F, "null instanceof F"); + assert.areEqual(2, checked, "Symbol.hasInstance in a normal function contructor - checked==2"); + assert.areEqual(true, true instanceof F, "true instanceof F"); + assert.areEqual(3, checked, "Symbol.hasInstance in a normal function contructor - checked==3"); + assert.areEqual(true, false instanceof F, "false instanceof F"); + assert.areEqual(4, checked, "Symbol.hasInstance in a normal function contructor - checked==4"); + assert.areEqual(true, 0 instanceof F, "0 instanceof F"); + assert.areEqual(5, checked, "Symbol.hasInstance in a normal function contructor - checked==5"); + assert.areEqual(true, 1.5e16 instanceof F, "1.5e16 instanceof F"); + assert.areEqual(6, checked, "Symbol.hasInstance in a normal function contructor - checked==6"); + assert.areEqual(true, NaN instanceof F, "NaN instanceof F"); + assert.areEqual(7, checked, "Symbol.hasInstance in a normal function contructor - checked==7"); + assert.areEqual(true, '' instanceof F, "'' instanceof F"); + assert.areEqual(8, checked, "Symbol.hasInstance in a normal function contructor - checked==8"); + assert.areEqual(true, 'abc' instanceof F, "'abc' instanceof F"); + assert.areEqual(9, checked, "Symbol.hasInstance in a normal function contructor - checked==9"); + assert.areEqual(true, {} instanceof F, "{} instanceof F"); + assert.areEqual(10, checked, "Symbol.hasInstance in a normal function contructor - checked==10"); + assert.areEqual(true, function(){} instanceof F, "function(){} instanceof F"); + assert.areEqual(11, checked, "Symbol.hasInstance in a normal function contructor - checked==11"); + } + }, + { + name: "change Symbol.hasInstance property of a non-function objects", + body: function() { + [ + {}, + {0:1,"length":1}, + [], + [0,1,2], + ['abc'], + ].forEach(function(item) { + testInstanceof(item); + }); + + function testInstanceof(O) { + var checked = 0; + + var oldf = O[Symbol.hasInstance]; + O[Symbol.hasInstance] = function() { + checked++; + return true; + }; + assertInstanceOf(O); + O[Symbol.hasInstance] = oldf; + + checked = 0; + var desc = Object.getOwnPropertyDescriptor(O, Symbol.hasInstance); + Object.defineProperty(O, Symbol.hasInstance, { + value: function () { + checked++; + return true; + } + }); + assertInstanceOf(O); + Object.defineProperty(O, Symbol.hasInstance, desc); + + function assertInstanceOf(O) { + assert.areEqual(true, undefined instanceof O, "undefined instanceof O"); + assert.areEqual(1, checked, "Symbol.hasInstance in a non-function object - checked==1"); + assert.areEqual(true, null instanceof O, "null instanceof O"); + assert.areEqual(2, checked, "Symbol.hasInstance in a non-function object - checked==2"); + assert.areEqual(true, true instanceof O, "true instanceof O"); + assert.areEqual(3, checked, "Symbol.hasInstance in a non-function object - checked==3"); + assert.areEqual(true, false instanceof O, "false instanceof O"); + assert.areEqual(4, checked, "Symbol.hasInstance in a non-function object - checked==4"); + assert.areEqual(true, 0 instanceof O, "0 instanceof O"); + assert.areEqual(5, checked, "Symbol.hasInstance in a non-function object - checked==5"); + assert.areEqual(true, 1.5e16 instanceof O, "1.5e16 instanceof O"); + assert.areEqual(6, checked, "Symbol.hasInstance in a non-function object - checked==6"); + assert.areEqual(true, NaN instanceof O, "NaN instanceof O"); + assert.areEqual(7, checked, "Symbol.hasInstance in a non-function object - checked==7"); + assert.areEqual(true, '' instanceof O, "'' instanceof O"); + assert.areEqual(8, checked, "Symbol.hasInstance in a non-function object - checked==8"); + assert.areEqual(true, 'abc' instanceof O, "'abc' instanceof O"); + assert.areEqual(9, checked, "Symbol.hasInstance in a non-function object - checked==9"); + assert.areEqual(true, {} instanceof O, "{} instanceof O"); + assert.areEqual(10, checked, "Symbol.hasInstance in a non-function object - checked==10"); + assert.areEqual(true, function(){} instanceof O, "function(){} instanceof O"); + assert.areEqual(11, checked, "Symbol.hasInstance in a non-function object - checked==11"); + } + } + } + }, + { + name: "change Symbol.hasInstance property of a bound function constructor", + body: function() { + var F = function (a, b) { + this.x = a; + this.y = b; + } + var BoundF = F.bind(1,2); + var checked = 0; + + Object.defineProperty(F, Symbol.hasInstance, { + value: function () { + checked++; + return true; + } + }); + + assert.areEqual(true, BoundF instanceof F, "BoundF instanceof F"); + assert.areEqual(1, checked, "Symbol.hasInstance in a function contructor bound - checked==1"); + assert.areEqual(true, Object.create(BoundF) instanceof F, "Object.create(BoundF) instanceof f"); + assert.areEqual(2, checked, "Symbol.hasInstance in a function contructor bound - checked==2"); + assert.areEqual(true, new BoundF() instanceof F, "new BoundF() instanceof F"); + assert.areEqual(3, checked, "Symbol.hasInstance in a function contructor bound - checked==3"); + assert.areEqual(true, Object.create(F.prototype) instanceof BoundF, "Object.create(F.prototype) instanceof F"); + assert.areEqual(true, new F() instanceof BoundF, "instanceof f"); + } + }, + { + name: "change Symbol.hasInstance property of a proxy of function constructor", + body: function() { + function Foo() { }; + var checked = 0; + var checkedString = []; + + Object.defineProperty(Foo, Symbol.hasInstance, { + value: function () { + checked++; + return false; + } + }); + + var ProxyFoo = new Proxy(Foo, { + get : function (target, property){ + checkedString.push(property.toString()); + return Reflect.get(target, property); + } + }); + + assert.areEqual(false, new ProxyFoo() instanceof ProxyFoo, "new ProxyFoo() instanceof ProxyFoo"); + assert.areEqual(1, checked, "Symbol.hasInstance in a function contructor through proxy - checked==1"); + assert.areEqual(['Symbol(Symbol.hasInstance)'], checkedString, "checkedString==['Symbol(Symbol.hasInstance)']"); + assert.areEqual(false, new ProxyFoo() instanceof Foo, "new ProxyFoo() instanceof Foo"); + assert.areEqual(2, checked, "Symbol.hasInstance in a function contructor through proxy - checked==2"); + } + }, + { + name: "change Symbol.hasInstance property of a bound proxy of function constructor", + body: function() { + function Foo() { }; + var checked = 0; + var checkedString = []; + + Object.defineProperty(Foo, Symbol.hasInstance, { + value: function () { + checked++; + return false; + } + }); + + var ProxyFoo = new Proxy(Foo, { + get : function (target, property){ + checkedString.push(property.toString()); + return Reflect.get(target, property); + } + }); + + var BP = ProxyFoo.bind(); + + assert.areEqual(false, BP instanceof ProxyFoo, "BP instanceof ProxyFoo"); + assert.areEqual(1, checked, "Symbol.hasInstance in a function contructor through bound proxy - checked==1"); + assert.areEqual(['bind','length','name','Symbol(Symbol.hasInstance)'], checkedString, "checkedString value"); + } + }, + { + name: "instanceof operator and default instOfHandler gets 'prototype' property of right-hand side", + body: function() { + [ + undefined, + null, + true, + false, + 'string', + Symbol(), + 0, + ].forEach(function(item) { + testInstanceof(item, function(){}); + }); + + function testInstanceof(prototypeObj, O) { + O.prototype = prototypeObj; + + assert.throws(()=>{({}) instanceof O}, TypeError, "({}) instanceof O", "Function does not have a valid prototype object"); + assert.throws(()=>{({0:1,"length":1}) instanceof O}, TypeError, "({0:1,\"length\":1}) instanceof O", "Function does not have a valid prototype object"); + assert.throws(()=>{[] instanceof O}, TypeError, "[] instanceof O", "Function does not have a valid prototype object"); + assert.throws(()=>{[0,1,2] instanceof O}, TypeError, "[0,1,2] instanceof O", "Function does not have a valid prototype object"); + assert.throws(()=>{['abc'] instanceof O}, TypeError, "['abc'] instanceof O", "Function does not have a valid prototype object"); + assert.throws(()=>{(function(){}) instanceof O}, TypeError, "(function(){}) instanceof O", "Function does not have a valid prototype object"); + + assert.throws(()=>{O[Symbol.hasInstance]({})}, TypeError, "O[Symbol.hasInstance]({})", "Function does not have a valid prototype object"); + assert.throws(()=>{O[Symbol.hasInstance]({0:1,"length":1})}, TypeError, "O[Symbol.hasInstance]({0:1,\"length\":1})", "Function does not have a valid prototype object"); + assert.throws(()=>{O[Symbol.hasInstance]([])}, TypeError, "O[Symbol.hasInstance]([])", "Function does not have a valid prototype object"); + assert.throws(()=>{O[Symbol.hasInstance]([0,1,2])}, TypeError, "O[Symbol.hasInstance]([0,1,2])", "Function does not have a valid prototype object"); + assert.throws(()=>{O[Symbol.hasInstance](['abc'])}, TypeError, "O[Symbol.hasInstance](['abc'])", "Function does not have a valid prototype object"); + assert.throws(()=>{O[Symbol.hasInstance](function(){})}, TypeError, "O[Symbol.hasInstance](function(){})", "Function does not have a valid prototype object"); + } + } + }, + { + name: "instanceof operator calling user-defined instOfHandler converts the return value to boolean using ToBoolean abstract operation", + body: function() { + [ + [function() { return undefined; }, false], + [function() { return null; }, false], + [function() { return NaN; }, false], + [function() { return 1; }, true], + [function() { return 0; }, false], + [function() { return ''; }, false], + [function() { return 'abc'; }, true], + [function() { return Symbol(); }, true], + [function() { return {}; }, true], + ].forEach(function(item) { + testInstanceof(item[0], item[1], {}); + testInstanceof(item[0], item[1], []); + }); + + function testInstanceof(instOfHandler, expected, O) { + O[Symbol.hasInstance] = instOfHandler; + assert.areEqual(expected, undefined instanceof O, "undefined instanceof O"); + assert.areEqual(expected, null instanceof O, "null instanceof O"); + assert.areEqual(expected, true instanceof O, "true instanceof O"); + assert.areEqual(expected, false instanceof O, "false instanceof O"); + assert.areEqual(expected, 0 instanceof O, "0 instanceof O"); + assert.areEqual(expected, 1.5e16 instanceof O, "1.5e16 instanceof O"); + assert.areEqual(expected, NaN instanceof O, "NaN instanceof O"); + assert.areEqual(expected, '' instanceof O, "'' instanceof O"); + assert.areEqual(expected, 'abc' instanceof O, "'abc' instanceof O"); + assert.areEqual(expected, {} instanceof O, "{} instanceof O"); + assert.areEqual(expected, function(){} instanceof O, "function(){} instanceof O"); + } } - }); - print(({}) instanceof o); -} - -// bounded function -function test2() { - print('*** test2'); - var o = function (a, b) { - this.x = a; - this.y = b; - } - var bounded = o.bind(1, 2); - Object.defineProperty(o, Symbol.hasInstance, { - value: function () { - print('checked Symbol.hasInstance'); - return true; + }, + { + name: "instanceof operator calling OrdinaryHasInstance abstract operation returns false on non-object left-hand side values", + body: function() { + var F = function() {}; + [ + undefined, + null, + true, + false, + '', + 'abc', + Symbol(), + Symbol('abc'), + 0, + 1.5e16, + NaN, + ].forEach(function(item) { + assert.isFalse(item instanceof F, typeof(item) == ('symbol' ? 'Symbol' : item) + " instanceof F"); + }); } - }); - - var x = Object.create(bounded); - print((x) instanceof o); - print((bounded) instanceof o); -} - -// proxy of function -function test3() { - print('*** test3'); - function foo() { }; - Object.defineProperty(foo, Symbol.hasInstance, { - value: function () { - print('checked Symbol.hasInstance'); - return false; + }, + { + name: "properties of Function.prototype[Symbol.hasInstance]", + body: function() { + var desc = Object.getOwnPropertyDescriptor(Function.prototype, Symbol.hasInstance); + assert.areEqual(false, desc.enumerable, "protype:enumerable==false"); + assert.areEqual(false, desc.writable, "protype:writable==false"); + assert.areEqual(false, desc.configurable, "protype:configurable==false"); + + var f = Function.prototype[Symbol.hasInstance]; + + assert.areEqual(1, f.length, "Function.prototype[Symbol.hasInstance].length==1"); + desc = Object.getOwnPropertyDescriptor(f, 'length'); + assert.areEqual(false, desc.enumerable, "length:enumerable==false"); + assert.areEqual(false, desc.writable, "length:enumerable==false"); + assert.areEqual(true, desc.configurable, "length:enumerable==true"); + + assert.areEqual('[Symbol.hasInstance]', f.name, "Function.prototype[Symbol.hasInstance].name"); + desc = Object.getOwnPropertyDescriptor(f, 'name'); + assert.areEqual(false, desc.enumerable, "name:enumerable==false"); + assert.areEqual(false, desc.writable, "name:writable==false"); + assert.areEqual(true, desc.configurable, "name:configurable==true"); + + assert.areEqual(false, f.call(), "Function.prototype[Symbol.hasInstance].call()"); + assert.areEqual(false, f.call({}), "Function.prototype[Symbol.hasInstance].call({})"); } - }); - var proxy = new Proxy(foo, { - get : function (target, property){ - print(property.toString()); - return Reflect.get(target, property); + }, + { + name: "instanceof operator on callable object invokes get on 'prototype' property", + body: function() { + // method 'F' has no 'prototype' property + var F = Object.getOwnPropertyDescriptor({ get f() {} }, 'f').get; + Object.defineProperty(F, 'prototype', { + get: function() { + throw new Error('Hit prototype'); + } + }); + assert.throws(()=>{undefined instanceof F}, Error, "undefined instanceof F", 'Hit prototype'); } - }); - - var x = new proxy(); - print((x) instanceof proxy); -} - -// proxy of bounded function -function test4() { - print('*** test4'); - function foo() { }; - Object.defineProperty(foo, Symbol.hasInstance, { - value: function () { - print('checked Symbol.hasInstance'); - return false; + }, + { + name: "instanceof operator invokes [[getPrototypeOf]] internal method on left-hand side value", + body: function() { + + var p = new Proxy({}, { + getPrototypeOf: function() { + throw new Error('Hit getPrototypeOf'); + } + }); + var obj = Object.create(p); + obj.prototype = {}; + var F = function() {}; + + assert.throws(()=>{p instanceof F}, Error, "p instanceof F", 'Hit getPrototypeOf'); + assert.throws(()=>{obj instanceof F}, Error, "obj instanceof F", 'Hit getPrototypeOf'); } - }); - var proxy = new Proxy(foo, { - get: function (target, property) { - print(property.toString()); - return Reflect.get(target, property); + }, + { + name: "changing Symbol.hasIstance property on a function contructor invalidates inline cache", + body: function() { + var F = function() {} + + var changeHasInstance = function() { + Object.defineProperty(F, Symbol.hasInstance, { + value: function(inst) { return true; } + }); + } + + function func() { + return 0 instanceof F; + } + + var changed = false; + for (var i=0; i<100; i++) { + var x = func(); + assert.areEqual(changed, x, "i=="+i); + if (i==20) { + changeHasInstance(); + changed = true; + } + } + + } + }, + { + name: "changing 'prototype' property on a function contructor invalidates inline cache", + body: function() { + var F = function() {} + + var changeHasInstance = function() { + Object.defineProperty(F, 'prototype', { + value: Function.prototype + }); + } + + function func() { + return function(){} instanceof F; + } + + var changed = false; + for (var i=0; i<100; i++) { + var x = func(); + assert.areEqual(changed, x, "i=="+i); + if (i==20) { + changeHasInstance(); + changed = true; + } + } + } - }); + }, +]; - var x = proxy.bind(); - print((x) instanceof proxy); -} +testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" }); -test1(); -test2(); -test3(); -test4(); \ No newline at end of file diff --git a/test/es6/rlexe.xml b/test/es6/rlexe.xml index 3e3e76be183..fdd58be9189 100644 --- a/test/es6/rlexe.xml +++ b/test/es6/rlexe.xml @@ -1180,8 +1180,7 @@ ES6HasInstance.js - -es6HasInstance - ES6HasInstance.baseline + -es6HasInstance -args summary -endargs