0

Does anyone here know why many of the functions in the v8 API return MaybeLocal handles instead of simply Local types?

I understand that calls can fail, but the Local type already has an IsEmpty() method that could be easily queried anyways, and if one was already rigorously testing to see if Local types were empty before using them whenever they were returned by any v8 API functions in the older API, then MaybeLocal in the new API seems needlessly redundant. Short of sticking to an obsolete and no longer supported version of the v8 API, it seems there is no choice but to jump through the hoops of using MaybeLocal.

I'm just wondering what the rationale was for it, particularly since, as I said, you could already test a Local to see if it was empty anyways, and especially since trying to convert a MaybeLocal that is empty to a Local will outright crash the application.

markt1964
  • 2,638
  • 2
  • 22
  • 54

1 Answers1

2

Although Local<T> and MaybeLocal<T> may appear similar, they serve very different purposes.

MaybeLocal<T> is used when an API returns either a T or throws an error. In particular, the invariant try_catch.HasCaught() == maybe_result.IsEmpty() should hold true. There is also a Maybe<T> type which is used for APIs like Object::Set, which do not return a JavaScript value but may still throw.

Local<T> is used for everything else, and basically represents a nullable T reference. As an example, Isolate::GetCurrentContext may return an empty Local<Context>, but that is not because it threw, it will be empty because there was no current context.

snek
  • 1,980
  • 1
  • 15
  • 29
  • If a script was not given a name, it's my understanding that the Local returned by GetScriptName would contain a valid (blank) string, and not be an actual empty Local with no assigned value at all. – markt1964 Nov 22 '19 at 01:07
  • @markt1964 You're right, I chose a poor example. `String::Concat` or `Isolate::GetCurrentContext` would have been better. I'll update my answer. – snek Nov 22 '19 at 05:27
  • Okay... but why bother with MaybeLocal when returning Local types, when the Value would have also been empty anyways if an exception had occurred? – markt1964 Nov 22 '19 at 23:49
  • My point is that when calling object::get, for example, it returns a MaybeLocal, but in fact the only case when the Value it might have otherwise returned would be actually empty would be if an exception had occurred, 'undefined' being easily distinctive from empty. Why bother with MaybeLocal in such cases? – markt1964 Nov 25 '19 at 02:38
  • @markt1964 It uses `MaybeLocal` because it will be empty if there is a pending exception. From v8.h: `If an API method returns a MaybeLocal<>, the API method can potentially fail either because an exception is thrown, or because an exception is pending`. It's simply to disambiguate why an empty handle was returned. – snek Nov 25 '19 at 03:34
  • The value would also have been, however. My point is that for Values, it seems to serve no useful purpose. – markt1964 Nov 25 '19 at 06:46
  • @markt1964 the point is that you know why it's empty. It's not about adding new technical functionality. Regardless of whether you agree with that design choice, that's how it is. I'd appreciate you marking this as answered if you get a chance :) – snek Nov 25 '19 at 16:45
  • I cannot reasonably flag this as "answered" when it did not actually answer the point of my question. While your answer does give a plausible use for MaybeLocal for non javascript values such as Contexts or Templates, it does not explain the purpose of using it for actual Javascript values, which the current v8 API is absolutely full of. I have changed the title of my question to explciitly reflect this. – markt1964 Nov 25 '19 at 17:05
  • MaybeLocal: API result will be empty if exception is pending. Local: result will be empty for other various reasons. – snek Nov 25 '19 at 19:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/203054/discussion-between-markt1964-and-snek). – markt1964 Nov 25 '19 at 19:06