| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 522d5a3 commit fe5666f
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -769,19 +769,25 @@ Intercepted ContextifyContext::PropertyDeleterCallback( | |||
| 769 | 769 | // static | |
| 770 | 770 | void ContextifyContext::PropertyEnumeratorCallback( | |
| 771 | 771 | const PropertyCallbackInfo<Array>& args) { | |
| 772 | + // Named enumerator will be invoked on Object.keys, | ||
| 773 | + // Object.getOwnPropertyNames, Object.getOwnPropertySymbols, | ||
| 774 | + // Object.getOwnPropertyDescriptors, for...in, etc. operations. | ||
| 775 | + // Named enumerator should return all own non-indices property names, | ||
| 776 | + // including string properties and symbol properties. V8 will filter the | ||
| 777 | + // result array to match the expected symbol-only, enumerable-only with | ||
| 778 | + // NamedPropertyQueryCallback. | ||
| 772 | 779 | ContextifyContext* ctx = ContextifyContext::Get(args); | |
| 773 | 780 | ||
| 774 | 781 | // Still initializing | |
| 775 | 782 | if (IsStillInitializing(ctx)) return; | |
| 776 | 783 | ||
| 777 | 784 | Local<Array> properties; | |
| 778 | - // Only get named properties, exclude symbols and indices. | ||
| 785 | + // Only get own named properties, exclude indices. | ||
| 779 | 786 | if (!ctx->sandbox() | |
| 780 | 787 | ->GetPropertyNames( | |
| 781 | 788 | ctx->context(), | |
| 782 | - KeyCollectionMode::kIncludePrototypes, | ||
| 783 | - static_cast<PropertyFilter>(PropertyFilter::ONLY_ENUMERABLE | | ||
| 784 | - PropertyFilter::SKIP_SYMBOLS), | ||
| 789 | + KeyCollectionMode::kOwnOnly, | ||
| 790 | + static_cast<PropertyFilter>(PropertyFilter::ALL_PROPERTIES), | ||
| 785 | 791 | IndexFilter::kSkipIndices) | |
| 786 | 792 | .ToLocal(&properties)) | |
| 787 | 793 | return; | |
@@ -792,6 +798,12 @@ void ContextifyContext::PropertyEnumeratorCallback( | |||
| 792 | 798 | // static | |
| 793 | 799 | void ContextifyContext::IndexedPropertyEnumeratorCallback( | |
| 794 | 800 | const PropertyCallbackInfo<Array>& args) { | |
| 801 | + // Indexed enumerator will be invoked on Object.keys, | ||
| 802 | + // Object.getOwnPropertyNames, Object.getOwnPropertyDescriptors, for...in, | ||
| 803 | + // etc. operations. Indexed enumerator should return all own non-indices index | ||
| 804 | + // properties. V8 will filter the result array to match the expected | ||
| 805 | + // enumerable-only with IndexedPropertyQueryCallback. | ||
| 806 | + | ||
| 795 | 807 | Isolate* isolate = args.GetIsolate(); | |
| 796 | 808 | HandleScope scope(isolate); | |
| 797 | 809 | ContextifyContext* ctx = ContextifyContext::Get(args); | |
@@ -802,9 +814,15 @@ void ContextifyContext::IndexedPropertyEnumeratorCallback( | |||
| 802 | 814 | ||
| 803 | 815 | Local<Array> properties; | |
| 804 | 816 | ||
| 805 | - // By default, GetPropertyNames returns string and number property names, and | ||
| 806 | - // doesn't convert the numbers to strings. | ||
| 807 | - if (!ctx->sandbox()->GetPropertyNames(context).ToLocal(&properties)) return; | ||
| 817 | + // Only get own index properties. | ||
| 818 | + if (!ctx->sandbox() | ||
| 819 | + ->GetPropertyNames( | ||
| 820 | + context, | ||
| 821 | + KeyCollectionMode::kOwnOnly, | ||
| 822 | + static_cast<PropertyFilter>(PropertyFilter::SKIP_SYMBOLS), | ||
| 823 | + IndexFilter::kIncludeIndices) | ||
| 824 | + .ToLocal(&properties)) | ||
| 825 | + return; | ||
| 808 | 826 | ||
| 809 | 827 | std::vector<v8::Global<Value>> properties_vec; | |
| 810 | 828 | if (FromV8Array(context, properties, &properties_vec).IsNothing()) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,6 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | require('../common'); | |
| 3 | + const globalNames = require('../common/globals'); | ||
| 3 | 4 | const vm = require('vm'); | |
| 4 | 5 | const assert = require('assert'); | |
| 5 | 6 | ||
@@ -39,11 +40,62 @@ const cases = [ | |||
| 39 | 40 | key: 'value', | |
| 40 | 41 | }, | |
| 41 | 42 | }, | |
| 43 | + (() => { | ||
| 44 | + const obj = { | ||
| 45 | + __proto__: { | ||
| 46 | + [Symbol.toStringTag]: 'proto', | ||
| 47 | + }, | ||
| 48 | + }; | ||
| 49 | + Object.defineProperty(obj, '1', { | ||
| 50 | + value: 'value', | ||
| 51 | + enumerable: false, | ||
| 52 | + configurable: true, | ||
| 53 | + }); | ||
| 54 | + Object.defineProperty(obj, 'key', { | ||
| 55 | + value: 'value', | ||
| 56 | + enumerable: false, | ||
| 57 | + configurable: true, | ||
| 58 | + }); | ||
| 59 | + Object.defineProperty(obj, Symbol('symbol'), { | ||
| 60 | + value: 'value', | ||
| 61 | + enumerable: false, | ||
| 62 | + configurable: true, | ||
| 63 | + }); | ||
| 64 | + Object.defineProperty(obj, Symbol('symbol-enumerable'), { | ||
| 65 | + value: 'value', | ||
| 66 | + enumerable: true, | ||
| 67 | + configurable: true, | ||
| 68 | + }); | ||
| 69 | + return obj; | ||
| 70 | + })(), | ||
| 42 | 71 | ]; | |
| 43 | 72 | ||
| 44 | 73 | for (const [idx, obj] of cases.entries()) { | |
| 45 | 74 | const ctx = vm.createContext(obj); | |
| 46 | 75 | const globalObj = vm.runInContext('this', ctx); | |
| 47 | - const keys = Object.keys(globalObj); | ||
| 48 | - assert.deepStrictEqual(keys, Object.keys(obj), `Case ${idx} failed`); | ||
| 76 | + assert.deepStrictEqual(Object.keys(globalObj), Object.keys(obj), `Case ${idx} failed: Object.keys`); | ||
| 77 | + | ||
| 78 | + const ownPropertyNamesInner = difference(Object.getOwnPropertyNames(globalObj), globalNames.intrinsics); | ||
| 79 | + const ownPropertyNamesOuter = Object.getOwnPropertyNames(obj); | ||
| 80 | + assert.deepStrictEqual( | ||
| 81 | + ownPropertyNamesInner, | ||
| 82 | + ownPropertyNamesOuter, | ||
| 83 | + `Case ${idx} failed: Object.getOwnPropertyNames` | ||
| 84 | + ); | ||
| 85 | + | ||
| 86 | + // FIXME(legendecas): globalThis[@@toStringTag] is unconditionally | ||
| 87 | + // initialized to the sandbox's constructor name, even if it does not exist | ||
| 88 | + // on the sandbox object. This may incorrectly initialize the prototype | ||
| 89 | + // @@toStringTag on the globalThis as an own property, like | ||
| 90 | + // Window.prototype[@@toStringTag] should be a property on the prototype. | ||
| 91 | + assert.deepStrictEqual( | ||
| 92 | + Object.getOwnPropertySymbols(globalObj).filter((it) => it !== Symbol.toStringTag), | ||
| 93 | + Object.getOwnPropertySymbols(obj), | ||
| 94 | + `Case ${idx} failed: Object.getOwnPropertySymbols` | ||
| 95 | + ); | ||
| 49 | 96 | } | |
| 97 | + | ||
| 98 | + function difference(arrA, arrB) { | ||
| 99 | + const setB = new Set(arrB); | ||
| 100 | + return arrA.filter((x) => !setB.has(x)); | ||
| 101 | + }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,11 +15,9 @@ Object.defineProperty(sandbox, sym2, { value: true }); | |||
| 15 | 15 | ||
| 16 | 16 | const ctx = vm.createContext(sandbox); | |
| 17 | 17 | ||
| 18 | - // Sanity check | ||
| 19 | - // Please uncomment these when the test is no longer broken | ||
| 20 | - // assert.deepStrictEqual(Reflect.ownKeys(sandbox), ['a', 'b', sym1, sym2]); | ||
| 21 | - // assert.deepStrictEqual(Object.getOwnPropertyNames(sandbox), ['a', 'b']); | ||
| 22 | - // assert.deepStrictEqual(Object.getOwnPropertySymbols(sandbox), [sym1, sym2]); | ||
| 18 | + assert.deepStrictEqual(Reflect.ownKeys(sandbox), ['a', 'b', sym1, sym2]); | ||
| 19 | + assert.deepStrictEqual(Object.getOwnPropertyNames(sandbox), ['a', 'b']); | ||
| 20 | + assert.deepStrictEqual(Object.getOwnPropertySymbols(sandbox), [sym1, sym2]); | ||
| 23 | 21 | ||
| 24 | 22 | const nativeKeys = vm.runInNewContext('Reflect.ownKeys(this);'); | |
| 25 | 23 | const ownKeys = vm.runInContext('Reflect.ownKeys(this);', ctx); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,11 +15,9 @@ Object.defineProperty(sandbox, sym2, { value: true }); | |||
| 15 | 15 | ||
| 16 | 16 | const ctx = vm.createContext(sandbox); | |
| 17 | 17 | ||
| 18 | - // Sanity check | ||
| 19 | - // Please uncomment these when the test is no longer broken | ||
| 20 | - // assert.deepStrictEqual(Reflect.ownKeys(sandbox), ['a', 'b', sym1, sym2]); | ||
| 21 | - // assert.deepStrictEqual(Object.getOwnPropertyNames(sandbox), ['a', 'b']); | ||
| 22 | - // assert.deepStrictEqual(Object.getOwnPropertySymbols(sandbox), [sym1, sym2]); | ||
| 18 | + assert.deepStrictEqual(Reflect.ownKeys(sandbox), ['a', 'b', sym1, sym2]); | ||
| 19 | + assert.deepStrictEqual(Object.getOwnPropertyNames(sandbox), ['a', 'b']); | ||
| 20 | + assert.deepStrictEqual(Object.getOwnPropertySymbols(sandbox), [sym1, sym2]); | ||
| 23 | 21 | ||
| 24 | 22 | const nativeNames = vm.runInNewContext('Object.getOwnPropertyNames(this);'); | |
| 25 | 23 | const ownNames = vm.runInContext('Object.getOwnPropertyNames(this);', ctx); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,11 +15,9 @@ Object.defineProperty(sandbox, sym2, { value: true }); | |||
| 15 | 15 | ||
| 16 | 16 | const ctx = vm.createContext(sandbox); | |
| 17 | 17 | ||
| 18 | - // Sanity check | ||
| 19 | - // Please uncomment these when the test is no longer broken | ||
| 20 | - // assert.deepStrictEqual(Reflect.ownKeys(sandbox), ['a', 'b', sym1, sym2]); | ||
| 21 | - // assert.deepStrictEqual(Object.getOwnPropertyNames(sandbox), ['a', 'b']); | ||
| 22 | - // assert.deepStrictEqual(Object.getOwnPropertySymbols(sandbox), [sym1, sym2]); | ||
| 18 | + assert.deepStrictEqual(Reflect.ownKeys(sandbox), ['a', 'b', sym1, sym2]); | ||
| 19 | + assert.deepStrictEqual(Object.getOwnPropertyNames(sandbox), ['a', 'b']); | ||
| 20 | + assert.deepStrictEqual(Object.getOwnPropertySymbols(sandbox), [sym1, sym2]); | ||
| 23 | 21 | ||
| 24 | 22 | const nativeSym = vm.runInNewContext('Object.getOwnPropertySymbols(this);'); | |
| 25 | 23 | const ownSym = vm.runInContext('Object.getOwnPropertySymbols(this);', ctx); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments