I'm trying to create a native object and set its [Symbol.iterator] so that the object can be enumerated using for...of, but all I can find in the API is JsCreateSymbol() which creates a new, unique symbol.
Can you use JsGetPropertyIdFromSymbol? @MSLaguana did something similar recently in https://github.com/nodejs/node-chakracore/pull/375/ - maybe he can confirm?
JsGetPropertyIdFromSymbol() will work, but I need a JsValueRef for Symbol.iterator first. I can only create unique symbols with the API, it seems like.
It's a little convoluted, but you can fetch the global object, then from that get the Symbol object, then from that get the value of Symbol.iterator, and then JsGetPropertyIdFromSymbol from that, something like
JsValueRef global, symbol, symbolIterator;
JsPropertyIdRef symbolPropertyId, iteratorPropertyId, iteratorSymbolPropertyId;
const WCHAR * symbolString = L"Symbol";
const WCHAR * iteratorString = L"iterator";
JsGetPropertyIdFromName(symbolString, &symbolPropertyId);
JsGetPropertyIdFromName(iteratorString, &iteratorPropertyId);
JsGetGlobalObject(&global);
JsGetProperty(global, symbolPropertyId, &symbol);
JsGetProperty(symbol, iteratorPropertyId, &symbolIterator);
JsGetPropertyIdFromSymbol(symbolIterator, iteratorSymbolPropertyId);
It might be nice to expose the symbols mentioned in the spec through a nicer interface in the JSRT though.
@curtisman @liminzhu thoughts on whether this merits a new API? Given the multiple steps involved here, I would tend to agree with @MSLaguana that having something like JsGetWellKnownSymbol could be useful.
@MSLaguana's solution also won't work correctly if a script assigns something else to Symbol.iterator for some reason. That's not an issue in my case since this is done on initialization with a virgin context, but in general it might be a problem.
I don't think that's the case for the standard symbols: Symbol.iterator is a non-writable non-configurable (non-enumerable, but that's less relevant) property. However, it is true that global.Symbol is not protected in the same way, so someone could replace Symbol wholesale.
@digitalinfinity honestly I don't think @MSLaguana 's solution is too complicated and user can easily define a helper on top of what we already have. I'm fine with creating a new API, but I'm more towards leaving it given the current solution and that the API interface tends to focus on offering small building blocks, unless the new API can get us some perf gains on common scenarios.
May be a more generalize way to get "built-ins" might be the way to go? I think a lot of integrators would like to get the default "built-ins" before the script mess with it on the global.
Speaking about code complexity, I think a lot of that stems from having to go through the propertyId middleman when dealing with name/symbol properties. I almost always define the below helper when playing with jsrt, which is a bit unfortunate. But with that (or something similar for symbols), code can be simplified and shortened. I think of built-ins just as a special case where you get a property from global, which requires one extra step of calling JsGetGlobalObject.
void setProperty(JsValueRef object, const wchar_t *propertyName, JsValueRef property)
{
JsPropertyIdRef propertyId;
JsGetPropertyIdFromName(propertyName, &propertyId);
JsSetProperty(object, propertyId, property, true);
}
Good point though on giving embedders the ability to use default built-ins without worrying about user overriding them. That also means whatever API that comes out of this enables a new capability current APIs cannot achieve, which I am all in for 馃槃.
I think a lot of integrators would like to get the default "built-ins" before the script mess with it on the global.
Myself included. 馃槃
I think a lot of integrators would like to get the default "built-ins" before the script mess with it on the global.
Should we make a work item for this and close this question?
@dilijev No objection from me.
Most helpful comment
May be a more generalize way to get "built-ins" might be the way to go? I think a lot of integrators would like to get the default "built-ins" before the script mess with it on the global.