Closed Bug 1651732 Opened 4 years ago Closed 4 years ago

Accessing a proxy's property using a Symbol returned from a implicit object[Symbol.toPrimitive] throws "TypeError: can't convert symbol to string"

Categories

(Core :: JavaScript Engine: JIT, defect)

80 Branch
defect

Tracking

()

RESOLVED FIXED
mozilla80
Tracking Status
firefox80 --- fixed

People

(Reporter: akgrk2010, Assigned: anba)

Details

Attachments

(12 files)

6.69 KB, image/png
Details
6.44 KB, image/png
Details
8.30 KB, image/png
Details
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36

Steps to reproduce:

const object = {
Symbol.toPrimitive {
return(Symbol());
}
};

const proxy = (new Proxy({},{
get(object,property,proxy) {
return(property);
}
}));

//fails when c>=10
for (let c = 0;(c < 15);c++) {
try {
console.log(c,proxy[object]);
} catch (error) {
console.log(c,error);
}
}

works on: Firefox 50.0-52.9.0, Chrome
fails on: Firefox 53.0-78.0.1, Nightly 80.0a1

Windows 10 Pro 1909 64bits

Actual results:

Console output:
0 Symbol()
1 Symbol()
...
9 Symbol()
10 TypeError: can't convert symbol to string
11 TypeError: can't convert symbol to string
...
14 TypeError: can't convert symbol to string

Expected results:

0 Symbol()
1 Symbol()
...
14 Symbol()

Attached image Untitled.png
Attached image Untitled2.png
Attached image Untitled3.png

Doesn't reproduce with --no-blinterp, so probably some issue in CacheIR.

Status: UNCONFIRMED → NEW
Component: JavaScript: Standard Library → JavaScript Engine: JIT
Ever confirmed: true

I guess this happens:

  • We get into megamorphic state and call GetPropIRGenerator::tryAttachGenericProxy.
  • CacheIRCompiler::emitCallProxyGetByValueResult calls into js::ProxyGetPropertyByValue.
  • js::ProxyGetPropertyByValue in turn uses ValueToId, which basically calls ToString instead of ToPrimitive.
Assignee: nobody → andrebargull
Status: NEW → ASSIGNED

ValueToId() calls ToAtom() for objects, which isn't correct per spec,
instead ToPropertyKey() needs to be used here.

Similar to part 1, replace ToValueId() with ToPropertyKey().

Depends on D83052

Similar to part 1, replace ToValueId() with ToPropertyKey().

Depends on D83053

Similar to part 1, replace ToValueId() with ToPropertyKey().

Depends on D83054

Similar to part 1, replace ToValueId() with ToPropertyKey().

Depends on D83055

Similar to part 1, replace ToValueId() with ToPropertyKey().

Depends on D83056

These changes should result in no observable behaviour for their current usage.

intrinsic_DefineDataProperty:

  • Using ToPropertyKey also is a better match for the inlined, three argument
    form of _DefineDataProperty.

JS_ValueToId:

  • It looks like this function is only called with String values, so changing it
    to use ToPropertyKey won't result in any observable difference.

js::ValueToIdentifier:

  • This function will throw an error when symbols are encountered anyway, so we
    might as well change it to use ToPropertyKey.

Depends on D83057

Only call ValueToId for primitive values in preparation for the next patch
and instead call ToAtom for objects.

Depends on D83058

ValueToId turned out to be a pitfall we want to avoid, it looks quite similar
to ToPropertyKey, but is subtly different to that function.

Let's rename it to PrimitiveValueToId and assert its input is a primitive,
that should prevent any accidental use of that function when ToPropertyKey
should have been used instead.

Depends on D83059

Pushed by abutkovits@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/291f6b508e95
Part 1: Change ProxyGetPropertyByValue to use ToPropertyKey. r=jandem
https://hg.mozilla.org/integration/autoland/rev/a92e558e609a
Part 2: Change ProxySetPropertyByValue to use ToPropertyKey. r=jandem
https://hg.mozilla.org/integration/autoland/rev/59deaa77e027
Part 3: Change ProxyHas to use ToPropertyKey. r=jandem
https://hg.mozilla.org/integration/autoland/rev/f0857b845e88
Part 4: Change ProxyHasOwn to use ToPropertyKey. r=jandem
https://hg.mozilla.org/integration/autoland/rev/d8c48aa96578
Part 5: Change IonGetPropSuperIC::update to use ToPropertyKey. r=jandem
https://hg.mozilla.org/integration/autoland/rev/23cb097cdecc
Part 6: Change DebuggerObject to use ToPropertyKey. r=jandem
https://hg.mozilla.org/integration/autoland/rev/1612cbe2a958
Part 7: Change additional callers to use ToPropertyKey instead of ValueToId. r=jandem
https://hg.mozilla.org/integration/autoland/rev/7c0eb528d744
Part 8: Split ValueToId callers in js::Stringify. r=jandem
https://hg.mozilla.org/integration/autoland/rev/0cdd4a7f1bb3
Part 9: Rename ValueToId to PrimitiveValueToId and assert its input is a primitive. r=jandem
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: