Skip to content

More descriptive results for typeof expressions #60

@ELLIOTTCABLE

Description

@ELLIOTTCABLE

So, something like this is a pretty common pattern:

assert(typeof wrap === 'function')

    AssertionError:   # giraphe.es6.js:61

assert(typeof wrap === 'function')
       |           |
       "object"    false

--- [string] 'function'
+++ [string] typeof wrap
@@ -1,8 +1,6 @@
-function
+object


    + expected - actual

    -false
    +true

Although this works, I feel that this could easily be extended with more useful information: for instance, in most failing assertions, there's information about the object under test; but specifically in typeof's case, that gets lost, and it gets treated as a simple comparison of two static strings.

Here's something like what I'd expect to see (hastily cobbled together from the results for assert(wrap === 'function'), because it was an easy change :P:

    AssertionError:   # giraphe.es6.js:61

assert(typeof wrap === 'function')
       |      |    |
       |      |    false
       |      Object{}
       "object"

[string] 'function'
=> "function"
[Object] wrap
=> Object{}

--- [string] 'function'
+++ [string] typeof wrap
@@ -1,8 +1,6 @@
-function
+object


    + expected - actual

    -false
    +true

Activity

twada

twada commented on Jun 10, 2016

@twada
Member

Thank you for your question.

Unfortunately, it's a limitation of current implementation of power-assert. I cannot support typeof UnaryExpression since it potentially causes ReferenceError.

Let me explain. Given example.js,

var obj = {
    name: 'foo'
};

function capt (val) {
    return val;
}

console.log(typeof obj);  //=> 'object'
console.log(typeof capt(obj));  //=> 'object'

console.log(typeof doesNotExist);  //=> 'undefined'
console.log(typeof capt(doesNotExist));  //=> ReferenceError: doesNotExist is not defined

results in ReferenceError when executed. Since typeof operator can take variable that does not defined.

$ node explain.js
object
object
undefined
/Users/takuto/src/github.com/power-assert-js/power-assert/explain.js:13
console.log(typeof capt(doesNotExist));  //=> ReferenceError: doesNotExist is not defined
                        ^

ReferenceError: doesNotExist is not defined
    at Object.<anonymous> (/Users/takuto/src/github.com/power-assert-js/power-assert/explain.js:13:25)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)
    at Function.Module.runMain (module.js:575:10)
    at startup (node.js:160:18)
    at node.js:445:3
$

capt function is the simplest mimic of what power-assert is doing internally, so when I tried to capture typeof UnaryExpression like typeof foo, it always result in ReferenceError.

Since test tool should not change behavior of SUT (System Under Test), I gave up supporting typeof UnaryExpression.

Sorry for inconvenience. I'll write about this limitation to FAQ section in REAME. Thanks!

ELLIOTTCABLE

ELLIOTTCABLE commented on Jun 10, 2016

@ELLIOTTCABLE
Author

Wait, tho: can't you special-case typeof at the syntactic level?

i.e. anything else in JS becomes expr(expr(expr)) to
capt(expr(capt(expr(capt(expr))))) … of course, that makes sense; but
typeof is special, so it makes sense to special-case it: expr(typeof expr)) to capt(expr(capt(typeof expr !== 'undefined' && typeof capt(expr) or something like that

Sorry for being terse, am on phone. Let me know if confused, can re-explain
when at computer!
On Fri, Jun 10, 2016 at 4:08 AM Takuto Wada notifications@github.com
wrote:

Thank you for your question.

Unfortunately, it's a limitation of current implementation of
power-assert. I cannot support typeof UnaryExpression since it
potentially causes ReferenceError.

Let me explain. Given example.js,

var obj = {
name: 'foo'
};
function capt (val) {
return val;
}
console.log(typeof obj); //=> 'object'console.log(typeof capt(obj)); //=> 'object'
console.log(typeof doesNotExist); //=> 'undefined'console.log(typeof capt(doesNotExist)); //=> ReferenceError: doesNotExist is not defined

results in ReferenceError when executed. Since typeof operator can take
variable that does not defined.

$ node explain.js
object
object
undefined
/Users/takuto/src/github.com/power-assert-js/power-assert/explain.js:13
console.log(typeof capt(doesNotExist)); //=> ReferenceError: doesNotExist is not defined
^

ReferenceError: doesNotExist is not defined
at Object. (/Users/takuto/src/github.com/power-assert-js/power-assert/explain.js:13:25)
at Module._compile (module.js:541:32)
at Object.Module._extensions..js (module.js:550:10)
at Module.load (module.js:456:32)
at tryModuleLoad (module.js:415:12)
at Function.Module._load (module.js:407:3)
at Function.Module.runMain (module.js:575:10)
at startup (node.js:160:18)
at node.js:445:3
$

capt function is what power-assert is doing internally, so when I tried
to capture typeof UnaryExpression like typeof foo, it always result in
ReferenceError.

Since test tool should not change behavior of SUT (System Under Test), I
gave up supporting typeof UnaryExpression.

Sorry for inconvenience. I'll write about this limitation to FAQ section
in REAME. Thanks!


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
#60 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AAAAyLCpy5K5DD3F3w_aJSkHrQGOctSaks5qKSlrgaJpZM4IpEzA
.

ELLIOTTCABLE

ELLIOTTCABLE commented on Jun 10, 2016

@ELLIOTTCABLE
Author

Ah, immediately realized a problem with that, so pulled out my laptop after sending.

Here's the two solutions I see:

// foo( typeof bar )
var _t; capt(foo( (((_t = typeof bar) !== 'undefined' && capt(bar)), _t)))

That's fast, but the downside is that it evaluates bar twice; so it's only suitable for situations where bar is not a complicated expression: i.e. it's just a standalone identifier.

Now, I'm not convinced anything except a standalone identifier can trigger a ReferenceError, will need to check the spec, but if it can, then more complicated expressions can be transformed to:

// foo( typeof bar(widget widget widget) )
var _a, _b; _a = capt(widget widget widget); try { _b = capt_maybe(bar(_a)) }
    catch (e) { _b = capt_fail() }; capt(foo(_b))

… or something like that, I got bogged down halfway through trying to construct it.

I think I've said this elsewhere on this project, but just to iterate: I'm totally aware that this looks like a ton of work. Special-casing in the parser, special-casing in the generator, special-casing capturing-functions that may not be evaluated (in the case of the try/catch approach), it's all a mess. I do disagree with you in that I think it's possible, but “this is too much work right now, and is outside the scope of this project, I'm afraid” is an answer I'm prepared to accept. (=

ELLIOTTCABLE

ELLIOTTCABLE commented on Jun 8, 2017

@ELLIOTTCABLE
Author

Resurrecting — any input on my suggestions, @twada? I wouldn't mind submitting a pull-request for one of my solutions (whichever you prefer), if this behaviour is welcome.

twada

twada commented on Jun 8, 2017

@twada
Member

@ELLIOTTCABLE Thank you for resurrecting this issue.
This is in my someday task. Sorry for my late response.
I think the solution might be look like babel's typeof helper. Could be a bit simpler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @ELLIOTTCABLE@twada

        Issue actions

          More descriptive results for `typeof` expressions · Issue #60 · power-assert-js/power-assert