sindresorhus / caller-callsite

Get the callsite of the caller function
MIT License
53 stars 10 forks source link

Use getTypeName() instead of receiver #1

Closed tomhughes closed 8 years ago

tomhughes commented 8 years ago

As receiver is now a private property we can't see it in newer versions of Node.js so use getTypeName() instead.

I basically derived this from https://chromium.googlesource.com/v8/v8/+/4.3.49/src/messages.js?autodive=0%2F%2F#810 where we can see that getTypeName gets the type name (if any) of the receiver.

tomhughes commented 8 years ago

Well that seems to have other problems in older versions... It works in 4.2.4 though...

SamVerschueren commented 8 years ago

I'm not really familiar with the internals here, but why not use a fallback if getTypeName is not available?

if (c[i].getTypeName && c[i].getTypeName() !== null || c[i].receiver !== undefined) {
    caller = i;
    break;
}

Not sure if it will work though. Update .travis.yml to test on node 4 and 5

sudo: false
language: node_js
node_js:
  - '5'
  - '4'
  - '0.12'
  - '0.10'
tomhughes commented 8 years ago

Let's try something like that and see...

SamVerschueren commented 8 years ago

If I use the following piece of code

var receiver;

try {
    receiver = c[i].getTypeName();
} catch (err) {
    receiver = c[i].receiver;
}

if (receiver !== undefined) {
    caller = i;
    break;
}

it works in 0.10 and 0.12. But in Node > 4, the statement in the test path.basename(fixture().getFileName()) resolves to index.js and not to test.js which is why it fails.

I am not familiar with the internals so can't help you with why that's the case. But it might give you some usefull information.

tomhughes commented 8 years ago

That's because getTypeName returns null not undefined.

SamVerschueren commented 8 years ago

Aha! Good catch. This should do it

var hasReceiver;

try {
    hasReceiver = c[i].getTypeName() !== null;
} catch (err) {
    hasReceiver = c[i].receiver !== undefined;
}

if (hasReceiver) {
    caller = i;
    break;
}
SamVerschueren commented 8 years ago

Or this might be better

var receiver;

try {
    receiver = c[i].getTypeName();
} catch (err) {
    receiver = c[i].receiver;
}

if (receiver != undefined) {
    caller = i;
    break;
}
tomhughes commented 8 years ago

I was already trying your first version ;-)

tomhughes commented 8 years ago

Yay!

SamVerschueren commented 8 years ago

I think @sindresorhus would like the second version more :). Not sure though, you can leave it as is and update the PR when he finds the time to review it.

tomhughes commented 8 years ago

Well receiver would be misleading in that case, as it would sometimes be the object and sometimes the type of the object, but it's easy enough to change.

SamVerschueren commented 8 years ago

Ping @sindresorhus

But in the meantime, we can just drop 0.10 and 0.12

sindresorhus commented 8 years ago

Sorry. Totally missed this. Thank you @tomhughes :)