mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 17:03:07 +09:00
Compare commits
No commits in common. "main" and "13.2-release" have entirely different histories.
main
...
13.2-relea
493 changed files with 611 additions and 211980 deletions
|
|
@ -65,9 +65,9 @@ pref("@GUAO_PREF@.mewe.com", "Mozilla/5.0 (%OS_SLICE% rv:102.0) Gecko/20100101 F
|
|||
|
||||
// UA-sniffing domains that are "app/vendor-specific" and do not like Dactyloidae
|
||||
pref("@GUAO_PREF@.web.whatsapp.com","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36");
|
||||
pref("@GUAO_PREF@.youtube.com","Mozilla/5.0 (%OS_SLICE%; Win64; x64; rv:147.0) Gecko/20100101 Firefox/147.0");
|
||||
pref("@GUAO_PREF@.studio.youtube.com","Mozilla/5.0 (%OS_SLICE%; Win64; x64; rv:147.0) Gecko/20100101 Firefox/147.0");
|
||||
pref("@GUAO_PREF@.gaming.youtube.com","Mozilla/5.0 (%OS_SLICE%; Win64; x64; rv:147.0) Gecko/20100101 Firefox/147.0");
|
||||
pref("@GUAO_PREF@.youtube.com","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36");
|
||||
pref("@GUAO_PREF@.studio.youtube.com","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36");
|
||||
pref("@GUAO_PREF@.gaming.youtube.com","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36");
|
||||
|
||||
// The following domains do not like the Goanna slice
|
||||
pref("@GUAO_PREF@.bab.la","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@");
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
52.13.2.1
|
||||
52.13.2
|
||||
|
|
@ -1 +1 @@
|
|||
13.2.1
|
||||
13.2
|
||||
|
|
@ -138,207 +138,6 @@ StructuredCloneCallbacksError(JSContext* aCx,
|
|||
NS_WARNING("Failed to clone data.");
|
||||
}
|
||||
|
||||
struct SameThreadStreamTransferData
|
||||
{
|
||||
SameThreadStreamTransferData(JSContext* aCx, JS::HandleObject aRecord)
|
||||
: mRecord(aCx, aRecord)
|
||||
{}
|
||||
|
||||
~SameThreadStreamTransferData()
|
||||
{
|
||||
mRecord.reset();
|
||||
}
|
||||
|
||||
JS::PersistentRootedObject mRecord;
|
||||
};
|
||||
|
||||
bool
|
||||
CallStreamTransferHelper(JSContext* aCx,
|
||||
const char* aHelperName,
|
||||
JS::HandleValue aArgument,
|
||||
JS::MutableHandleValue aResult)
|
||||
{
|
||||
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
if (!global) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolve the stream extras lazily before looking up the internal helper.
|
||||
JS::Rooted<JS::Value> ignored(aCx);
|
||||
if (!JS_GetProperty(aCx, global, "WritableStream", &ignored)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> helper(aCx);
|
||||
if (!JS_GetProperty(aCx, global, aHelperName, &helper)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!helper.isObject() || !JS::IsCallable(&helper.toObject())) {
|
||||
aResult.setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> argument(aCx, aArgument);
|
||||
if (!JS_WrapValue(aCx, &argument)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return JS::Call(aCx, JS::UndefinedHandleValue, helper,
|
||||
JS::HandleValueArray(argument), aResult);
|
||||
}
|
||||
|
||||
bool
|
||||
TryWriteSameThreadStreamTransfer(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
const char* aHelperName,
|
||||
uint32_t aTransferTag,
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData,
|
||||
bool* aHandled)
|
||||
{
|
||||
*aHandled = false;
|
||||
|
||||
JS::Rooted<JS::Value> argument(aCx, JS::ObjectValue(*aObj));
|
||||
JS::Rooted<JS::Value> transferRecord(aCx);
|
||||
if (!CallStreamTransferHelper(aCx, aHelperName, argument, &transferRecord)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (transferRecord.isUndefined()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!transferRecord.isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> record(aCx, &transferRecord.toObject());
|
||||
SameThreadStreamTransferData* data =
|
||||
new SameThreadStreamTransferData(aCx, record);
|
||||
|
||||
*aTag = aTransferTag;
|
||||
*aOwnership = JS::SCTAG_TMO_CUSTOM;
|
||||
*aContent = data;
|
||||
*aExtraData = 0;
|
||||
*aHandled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TryWriteReadableStreamPortTransfer(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
nsTArray<MessagePortIdentifier>& aPortIdentifiers,
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData,
|
||||
bool* aHandled)
|
||||
{
|
||||
*aHandled = false;
|
||||
|
||||
JS::Rooted<JS::Value> argument(aCx, JS::ObjectValue(*aObj));
|
||||
JS::Rooted<JS::Value> transferPortValue(aCx);
|
||||
if (!CallStreamTransferHelper(aCx, "__uxpTransferReadableStreamPort",
|
||||
argument, &transferPortValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (transferPortValue.isUndefined()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!transferPortValue.isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> transferPortObj(aCx, &transferPortValue.toObject());
|
||||
MessagePort* port = nullptr;
|
||||
nsresult rv = UNWRAP_OBJECT(MessagePort, &transferPortObj, port);
|
||||
if (NS_FAILED(rv) || !port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*aExtraData = aPortIdentifiers.Length();
|
||||
MessagePortIdentifier* identifier = aPortIdentifiers.AppendElement();
|
||||
port->CloneAndDisentangle(*identifier);
|
||||
|
||||
*aTag = SCTAG_DOM_TRANSFERRED_READABLESTREAM;
|
||||
*aOwnership = JS::SCTAG_TMO_CUSTOM;
|
||||
*aContent = nullptr;
|
||||
*aHandled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ReadSameThreadStreamTransfer(JSContext* aCx,
|
||||
void* aContent,
|
||||
const char* aHelperName,
|
||||
JS::MutableHandleObject aReturnObject)
|
||||
{
|
||||
MOZ_ASSERT(aContent);
|
||||
SameThreadStreamTransferData* data =
|
||||
static_cast<SameThreadStreamTransferData*>(aContent);
|
||||
|
||||
JS::Rooted<JS::Value> record(aCx, JS::ObjectValue(*data->mRecord));
|
||||
JS::Rooted<JS::Value> result(aCx);
|
||||
if (!CallStreamTransferHelper(aCx, aHelperName, record, &result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!result.isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aReturnObject.set(&result.toObject());
|
||||
delete data;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ReadReadableStreamPortTransfer(JSContext* aCx,
|
||||
nsISupports* aParent,
|
||||
nsTArray<MessagePortIdentifier>& aPortIdentifiers,
|
||||
uint64_t aExtraData,
|
||||
JS::MutableHandleObject aReturnObject)
|
||||
{
|
||||
if (aExtraData >= aPortIdentifiers.Length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent);
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<MessagePort> port =
|
||||
MessagePort::Create(global, aPortIdentifiers[aExtraData], rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
rv.SuppressException();
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> portValue(aCx);
|
||||
if (!GetOrCreateDOMReflector(aCx, port, &portValue)) {
|
||||
JS_ClearPendingException(aCx);
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> result(aCx);
|
||||
if (!CallStreamTransferHelper(aCx,
|
||||
"__uxpReceiveReadableStreamTransferFromPort",
|
||||
portValue, &result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!result.isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aReturnObject.set(&result.toObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
const JSStructuredCloneCallbacks StructuredCloneHolder::sCallbacks = {
|
||||
|
|
@ -1576,35 +1375,6 @@ StructuredCloneHolder::CustomReadTransferHandler(JSContext* aCx,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread) {
|
||||
if (aTag == SCTAG_DOM_TRANSFERRED_WRITABLESTREAM) {
|
||||
return ReadSameThreadStreamTransfer(aCx, aContent,
|
||||
"__uxpReceiveWritableStreamTransfer",
|
||||
aReturnObject);
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_TRANSFERRED_READABLESTREAM) {
|
||||
return ReadSameThreadStreamTransfer(aCx, aContent,
|
||||
"__uxpReceiveReadableStreamTransfer",
|
||||
aReturnObject);
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_TRANSFERRED_TRANSFORMSTREAM) {
|
||||
return ReadSameThreadStreamTransfer(aCx, aContent,
|
||||
"__uxpReceiveTransformStreamTransfer",
|
||||
aReturnObject);
|
||||
}
|
||||
}
|
||||
|
||||
if ((mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::DifferentProcess) &&
|
||||
aTag == SCTAG_DOM_TRANSFERRED_READABLESTREAM) {
|
||||
MOZ_ASSERT(!aContent);
|
||||
return ReadReadableStreamPortTransfer(aCx, mParent, mPortIdentifiers,
|
||||
aExtraData,
|
||||
aReturnObject);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1673,55 +1443,6 @@ StructuredCloneHolder::CustomWriteTransferHandler(JSContext* aCx,
|
|||
}
|
||||
}
|
||||
|
||||
if (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread) {
|
||||
bool handled = false;
|
||||
if (!TryWriteSameThreadStreamTransfer(aCx, obj,
|
||||
"__uxpTransferWritableStream",
|
||||
SCTAG_DOM_TRANSFERRED_WRITABLESTREAM,
|
||||
aTag, aOwnership, aContent,
|
||||
aExtraData, &handled)) {
|
||||
return false;
|
||||
}
|
||||
if (handled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!TryWriteSameThreadStreamTransfer(aCx, obj,
|
||||
"__uxpTransferReadableStream",
|
||||
SCTAG_DOM_TRANSFERRED_READABLESTREAM,
|
||||
aTag, aOwnership, aContent,
|
||||
aExtraData, &handled)) {
|
||||
return false;
|
||||
}
|
||||
if (handled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!TryWriteSameThreadStreamTransfer(aCx, obj,
|
||||
"__uxpTransferTransformStream",
|
||||
SCTAG_DOM_TRANSFERRED_TRANSFORMSTREAM,
|
||||
aTag, aOwnership, aContent,
|
||||
aExtraData, &handled)) {
|
||||
return false;
|
||||
}
|
||||
if (handled) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::DifferentProcess) {
|
||||
bool handled = false;
|
||||
if (!TryWriteReadableStreamPortTransfer(aCx, obj, mPortIdentifiers,
|
||||
aTag, aOwnership, aContent,
|
||||
aExtraData, &handled)) {
|
||||
return false;
|
||||
}
|
||||
if (handled) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1759,26 +1480,6 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
|
|||
delete data;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((aTag == SCTAG_DOM_TRANSFERRED_WRITABLESTREAM ||
|
||||
aTag == SCTAG_DOM_TRANSFERRED_READABLESTREAM ||
|
||||
aTag == SCTAG_DOM_TRANSFERRED_TRANSFORMSTREAM) &&
|
||||
mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread) {
|
||||
MOZ_ASSERT(aContent);
|
||||
SameThreadStreamTransferData* data =
|
||||
static_cast<SameThreadStreamTransferData*>(aContent);
|
||||
delete data;
|
||||
return;
|
||||
}
|
||||
|
||||
if (aTag == SCTAG_DOM_TRANSFERRED_READABLESTREAM &&
|
||||
(mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread ||
|
||||
mStructuredCloneScope == StructuredCloneScope::DifferentProcess)) {
|
||||
MOZ_ASSERT(!aContent);
|
||||
MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
|
||||
MessagePort::ForceClose(mPortIdentifiers[aExtraData]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -68,11 +68,6 @@ enum StructuredCloneTags {
|
|||
// This tag is used by both main thread and workers.
|
||||
SCTAG_DOM_URLSEARCHPARAMS,
|
||||
|
||||
// Same-thread transferable stream records. These are not supported by IDB.
|
||||
SCTAG_DOM_TRANSFERRED_READABLESTREAM,
|
||||
SCTAG_DOM_TRANSFERRED_WRITABLESTREAM,
|
||||
SCTAG_DOM_TRANSFERRED_TRANSFORMSTREAM,
|
||||
|
||||
// When adding a new tag for IDB, please don't add it to the end of the list!
|
||||
// Tags that are supported by IDB must not ever change. See the static assert
|
||||
// in IDBObjectStore.cpp, method CommonStructuredCloneReadCallback.
|
||||
|
|
|
|||
|
|
@ -127,29 +127,7 @@ void
|
|||
nsDOMTokenList::AddInternal(const nsAttrValue* aAttr,
|
||||
const nsTArray<nsString>& aTokens)
|
||||
{
|
||||
if (!mElement || aTokens.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hot path: single-token classList.add() when the class is already present.
|
||||
// Skip attribute rebuild and SetAttr entirely (avoids mutation observers /
|
||||
// style invalidation). Frameworks hit this constantly.
|
||||
if (aTokens.Length() == 1) {
|
||||
const nsString& token = aTokens[0];
|
||||
if (aAttr && aAttr->Contains(token)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString resultStr;
|
||||
if (aAttr) {
|
||||
aAttr->ToString(resultStr);
|
||||
if (!resultStr.IsEmpty() &&
|
||||
!nsContentUtils::IsHTMLWhitespace(resultStr.Last())) {
|
||||
resultStr.Append(' ');
|
||||
}
|
||||
}
|
||||
resultStr.Append(token);
|
||||
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, resultStr, true);
|
||||
if (!mElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -183,11 +161,6 @@ nsDOMTokenList::AddInternal(const nsAttrValue* aAttr,
|
|||
addedClasses.AppendElement(aToken);
|
||||
}
|
||||
|
||||
// No new tokens: leave the attribute untouched (do not create class="").
|
||||
if (!oneWasAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, resultStr, true);
|
||||
}
|
||||
|
||||
|
|
@ -217,37 +190,20 @@ nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
|
|||
{
|
||||
MOZ_ASSERT(aAttr, "Need an attribute");
|
||||
|
||||
if (aTokens.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hot path: single-token classList.remove() when the class is absent.
|
||||
if (aTokens.Length() == 1 && !aAttr->Contains(aTokens[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString input;
|
||||
aAttr->ToString(input);
|
||||
|
||||
WhitespaceTokenizer tokenizer(input);
|
||||
nsAutoString output;
|
||||
bool removed = false;
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
auto& currentToken = tokenizer.nextToken();
|
||||
if (aTokens.Contains(currentToken)) {
|
||||
removed = true;
|
||||
continue;
|
||||
if (!aTokens.Contains(currentToken)) {
|
||||
if (!output.IsEmpty()) {
|
||||
output.Append(char16_t(' '));
|
||||
}
|
||||
output.Append(currentToken);
|
||||
}
|
||||
if (!output.IsEmpty()) {
|
||||
output.Append(char16_t(' '));
|
||||
}
|
||||
output.Append(currentToken);
|
||||
}
|
||||
|
||||
// Token set unchanged: skip SetAttr to avoid style/mutation work.
|
||||
if (!removed) {
|
||||
return;
|
||||
}
|
||||
|
||||
mElement->SetAttr(kNameSpaceID_None, mAttrAtom, output, true);
|
||||
|
|
@ -346,16 +302,6 @@ nsDOMTokenList::ReplaceInternal(const nsAttrValue* aAttr,
|
|||
const nsAString& aToken,
|
||||
const nsAString& aNewToken)
|
||||
{
|
||||
// Replacing a token with itself cannot change the token set.
|
||||
if (aToken.Equals(aNewToken)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Old token absent: no update (and avoid rewriting whitespace).
|
||||
if (!aAttr->Contains(aToken)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString attribute;
|
||||
aAttr->ToString(attribute);
|
||||
|
||||
|
|
|
|||
|
|
@ -1929,9 +1929,6 @@ public:
|
|||
{
|
||||
ProcessGlobal* global = ProcessGlobal::Get();
|
||||
MOZ_ASSERT(!aRunInGlobalScope);
|
||||
if (NS_WARN_IF(!global)) {
|
||||
return false;
|
||||
}
|
||||
global->LoadScript(aURL);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2334,7 +2334,8 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
|
|||
}
|
||||
|
||||
if (aRequest->IsModuleRequest()) {
|
||||
AutoCurrentScriptUpdater scriptUpdater(this, aRequest->Element());
|
||||
// For modules, currentScript is set to null.
|
||||
AutoCurrentScriptUpdater scriptUpdater(this, nullptr);
|
||||
|
||||
ModuleLoadRequest* request = aRequest->AsModuleRequest();
|
||||
MOZ_ASSERT(request->mModuleScript);
|
||||
|
|
|
|||
|
|
@ -301,7 +301,6 @@ LoadContextOptions(const char* aPrefName, void* /* aClosure */)
|
|||
.setAsyncStack(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asyncstack")))
|
||||
.setWerror(GetWorkerPref<bool>(NS_LITERAL_CSTRING("werror")))
|
||||
.setStreams(GetWorkerPref<bool>(NS_LITERAL_CSTRING("streams")))
|
||||
.setWeakRefs(GetWorkerPref<bool>(NS_LITERAL_CSTRING("weakrefs")))
|
||||
.setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict")))
|
||||
.setArrayProtoValues(GetWorkerPref<bool>(
|
||||
NS_LITERAL_CSTRING("array_prototype_values")));
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ WORKER_SIMPLE_PREF("dom.serviceWorkers.openWindow.enabled", OpenWindowEnabled, O
|
|||
WORKER_SIMPLE_PREF("dom.storageManager.enabled", StorageManagerEnabled, STORAGEMANAGER_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.streams.enabled", StreamsEnabled, STREAMS_ENABLED)
|
||||
WORKER_SIMPLE_PREF("javascript.options.weakrefs", WeakRefsEnabled, WEAKREFS_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED)
|
||||
WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
|
||||
WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK)
|
||||
|
|
|
|||
|
|
@ -952,38 +952,12 @@ using namespace std;
|
|||
void
|
||||
imgCacheQueue::Remove(imgCacheEntry* entry)
|
||||
{
|
||||
uint64_t index = mQueue.IndexOf(entry);
|
||||
if (index == queueContainer::NoIndex) {
|
||||
return;
|
||||
queueContainer::iterator it = find(mQueue.begin(), mQueue.end(), entry);
|
||||
if (it != mQueue.end()) {
|
||||
mSize -= (*it)->GetDataSize();
|
||||
mQueue.erase(it);
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
mSize -= mQueue[index]->GetDataSize();
|
||||
|
||||
// If the queue is clean and this is the first entry,
|
||||
// then we can efficiently remove the entry without
|
||||
// dirtying the sort order.
|
||||
if (!IsDirty() && index == 0) {
|
||||
std::pop_heap(mQueue.begin(), mQueue.end(),
|
||||
imgLoader::CompareCacheEntries);
|
||||
mQueue.RemoveElementAt(mQueue.Length() - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove from the middle of the list. This potentially
|
||||
// breaks the binary heap sort order.
|
||||
mQueue.RemoveElementAt(index);
|
||||
|
||||
// If we only have one entry or the queue is empty, though,
|
||||
// then the sort order is still effectively good.
|
||||
// Simply refresh the list to clear the dirty flag.
|
||||
if (mQueue.Length() <= 1) {
|
||||
Refresh();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise we must mark the queue dirty and potentially
|
||||
// trigger an expensive sort later.
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -992,26 +966,23 @@ imgCacheQueue::Push(imgCacheEntry* entry)
|
|||
mSize += entry->GetDataSize();
|
||||
|
||||
RefPtr<imgCacheEntry> refptr(entry);
|
||||
mQueue.AppendElement(Move(refptr));
|
||||
// If we're not dirty already, then we can efficiently add this to the binary heap immediately.
|
||||
if (!IsDirty()) {
|
||||
std::push_heap(mQueue.begin(), mQueue.end(), imgLoader::CompareCacheEntries);
|
||||
}
|
||||
mQueue.push_back(refptr);
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
already_AddRefed<imgCacheEntry>
|
||||
imgCacheQueue::Pop()
|
||||
{
|
||||
if (mQueue.IsEmpty()) {
|
||||
if (mQueue.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (IsDirty()) {
|
||||
Refresh();
|
||||
}
|
||||
|
||||
RefPtr<imgCacheEntry> entry = mQueue[0];
|
||||
std::pop_heap(mQueue.begin(), mQueue.end(), imgLoader::CompareCacheEntries);
|
||||
RefPtr<imgCacheEntry> entry = Move(mQueue.LastElement());
|
||||
mQueue.RemoveElementAt(mQueue.Length() - 1);
|
||||
mQueue.pop_back();
|
||||
|
||||
mSize -= entry->GetDataSize();
|
||||
return entry.forget();
|
||||
|
|
@ -1020,7 +991,6 @@ imgCacheQueue::Pop()
|
|||
void
|
||||
imgCacheQueue::Refresh()
|
||||
{
|
||||
// Re-heap the list. This is an O(3 * n) operation and best avoided if possible.
|
||||
std::make_heap(mQueue.begin(), mQueue.end(), imgLoader::CompareCacheEntries);
|
||||
mDirty = false;
|
||||
}
|
||||
|
|
@ -1040,13 +1010,7 @@ imgCacheQueue::IsDirty()
|
|||
uint32_t
|
||||
imgCacheQueue::GetNumElements() const
|
||||
{
|
||||
return mQueue.Length();
|
||||
}
|
||||
|
||||
bool
|
||||
imgCacheQueue::Contains(imgCacheEntry* aEntry) const
|
||||
{
|
||||
return mQueue.Contains(aEntry);
|
||||
return mQueue.size();
|
||||
}
|
||||
|
||||
imgCacheQueue::iterator
|
||||
|
|
@ -1638,11 +1602,7 @@ void
|
|||
imgLoader::CacheEntriesChanged(bool aForChrome, int32_t aSizeDiff /* = 0 */)
|
||||
{
|
||||
imgCacheQueue& queue = GetCacheQueue(aForChrome);
|
||||
// We only need to dirty the queue if there is any sorting taking place.
|
||||
// Empty or single-entry lists can't become dirty.
|
||||
if (queue.GetNumElements() > 1) {
|
||||
queue.MarkDirty();
|
||||
}
|
||||
queue.MarkDirty();
|
||||
queue.UpdateSize(aSizeDiff);
|
||||
}
|
||||
|
||||
|
|
@ -1671,9 +1631,7 @@ imgLoader::CheckCacheLimits(imgCacheTable& cache, imgCacheQueue& queue)
|
|||
}
|
||||
|
||||
if (entry) {
|
||||
// We just popped this entry from the queue, so pass AlreadyRemoved
|
||||
// to avoid searching the queue again in RemoveFromCache.
|
||||
RemoveFromCache(entry, QueueState::AlreadyRemoved);
|
||||
RemoveFromCache(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1972,7 +1930,7 @@ imgLoader::RemoveFromCache(const ImageCacheKey& aKey)
|
|||
}
|
||||
|
||||
bool
|
||||
imgLoader::RemoveFromCache(imgCacheEntry* entry, QueueState aQueueState)
|
||||
imgLoader::RemoveFromCache(imgCacheEntry* entry)
|
||||
{
|
||||
LOG_STATIC_FUNC(gImgLog, "imgLoader::RemoveFromCache entry");
|
||||
|
||||
|
|
@ -1988,24 +1946,13 @@ imgLoader::RemoveFromCache(imgCacheEntry* entry, QueueState aQueueState)
|
|||
|
||||
cache.Remove(key);
|
||||
|
||||
if (queue.IsDirty()) {
|
||||
queue.Refresh();
|
||||
}
|
||||
|
||||
if (entry->HasNoProxies()) {
|
||||
LOG_STATIC_FUNC(gImgLog,
|
||||
"imgLoader::RemoveFromCache removing from tracker");
|
||||
if (mCacheTracker) {
|
||||
mCacheTracker->RemoveObject(entry);
|
||||
}
|
||||
// Only search the queue to remove the entry if its possible it might
|
||||
// be in the queue. If we know its not in the queue this would be
|
||||
// wasted work.
|
||||
MOZ_ASSERT_IF(aQueueState == QueueState::AlreadyRemoved,
|
||||
!queue.Contains(entry));
|
||||
if (aQueueState == QueueState::MaybeExists) {
|
||||
queue.Remove(entry);
|
||||
}
|
||||
queue.Remove(entry);
|
||||
}
|
||||
|
||||
entry->SetEvicted(true);
|
||||
|
|
@ -2050,13 +1997,13 @@ imgLoader::EvictEntries(imgCacheQueue& aQueueToClear)
|
|||
// We have to make a temporary, since RemoveFromCache removes the element
|
||||
// from the queue, invalidating iterators.
|
||||
nsTArray<RefPtr<imgCacheEntry> > entries(aQueueToClear.GetNumElements());
|
||||
for (auto i = aQueueToClear.begin(); i != aQueueToClear.end(); ++i) {
|
||||
for (imgCacheQueue::const_iterator i = aQueueToClear.begin();
|
||||
i != aQueueToClear.end(); ++i) {
|
||||
entries.AppendElement(*i);
|
||||
}
|
||||
|
||||
// Iterate in reverse order to minimize array copying.
|
||||
for (auto& entry : entries) {
|
||||
if (!RemoveFromCache(entry)) {
|
||||
for (uint32_t i = 0; i < entries.Length(); ++i) {
|
||||
if (!RemoveFromCache(entries[i])) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,8 +178,7 @@ public:
|
|||
uint32_t GetSize() const;
|
||||
void UpdateSize(int32_t diff);
|
||||
uint32_t GetNumElements() const;
|
||||
bool Contains(imgCacheEntry* aEntry) const;
|
||||
typedef nsTArray<RefPtr<imgCacheEntry> > queueContainer;
|
||||
typedef std::vector<RefPtr<imgCacheEntry> > queueContainer;
|
||||
typedef queueContainer::iterator iterator;
|
||||
typedef queueContainer::const_iterator const_iterator;
|
||||
|
||||
|
|
@ -317,16 +316,7 @@ public:
|
|||
nsresult InitCache();
|
||||
|
||||
bool RemoveFromCache(const ImageCacheKey& aKey);
|
||||
|
||||
// Enumeration describing if a given entry is in the cache queue or not.
|
||||
// There are some cases we know the entry is definitely not in the queue.
|
||||
enum class QueueState {
|
||||
MaybeExists,
|
||||
AlreadyRemoved
|
||||
};
|
||||
|
||||
bool RemoveFromCache(imgCacheEntry* entry,
|
||||
QueueState aQueueState = QueueState::MaybeExists);
|
||||
bool RemoveFromCache(imgCacheEntry* entry);
|
||||
|
||||
bool PutIntoCache(const ImageCacheKey& aKey, imgCacheEntry* aEntry);
|
||||
|
||||
|
|
|
|||
|
|
@ -253,67 +253,6 @@ function ArraySort(comparefn) {
|
|||
return MergeSort(O, len, comparefn);
|
||||
}
|
||||
|
||||
// ES2023 22.1.3.30 Array.prototype.toSorted ( comparefn )
|
||||
function ArrayToSorted(comparefn) {
|
||||
if (comparefn !== undefined) {
|
||||
if (!IsCallable(comparefn)) {
|
||||
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, comparefn));
|
||||
}
|
||||
}
|
||||
|
||||
// Step 1: Let O be ? ToObject(this). Let len be ? ToLength(O.length).
|
||||
var O = ToObject(this);
|
||||
var len = ToLength(O.length);
|
||||
|
||||
// Step 2: Snapshot values in ascending index order into a List.
|
||||
var items = new List();
|
||||
var itemsLen = len;
|
||||
for (var k = 0; k < len; k++) {
|
||||
items[k] = O[k];
|
||||
}
|
||||
|
||||
// Step 3: Create SortCompare per spec.
|
||||
var wrappedCompareFn = comparefn;
|
||||
var sortCompare;
|
||||
if (wrappedCompareFn === undefined) {
|
||||
sortCompare = function(x, y) {
|
||||
if (x === undefined)
|
||||
return y === undefined ? 0 : 1;
|
||||
if (y === undefined)
|
||||
return -1;
|
||||
|
||||
var xString = ToString(x);
|
||||
var yString = ToString(y);
|
||||
if (xString < yString)
|
||||
return -1;
|
||||
if (xString > yString)
|
||||
return 1;
|
||||
return 0;
|
||||
};
|
||||
} else {
|
||||
sortCompare = function(x, y) {
|
||||
if (x === undefined)
|
||||
return y === undefined ? 0 : 1;
|
||||
if (y === undefined)
|
||||
return -1;
|
||||
|
||||
var v = ToNumber(wrappedCompareFn(x, y));
|
||||
return v !== v ? 0 : v;
|
||||
};
|
||||
}
|
||||
|
||||
// Step 4: Sort the snapshot List using SortCompare.
|
||||
if (itemsLen > 1)
|
||||
MergeSort(items, itemsLen, sortCompare);
|
||||
|
||||
// Step 5: Create result array and write sorted values.
|
||||
var A = ArraySpeciesCreate(O, len);
|
||||
for (var j = 0; j < itemsLen; j++)
|
||||
_DefineDataProperty(A, j, items[j]);
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.18. */
|
||||
function ArrayForEach(callbackfn/*, thisArg*/) {
|
||||
/* Step 1. */
|
||||
|
|
|
|||
|
|
@ -47,12 +47,10 @@
|
|||
#include "builtin/AtomicsObject.h"
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "builtin/Promise.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsnum.h"
|
||||
|
|
@ -60,9 +58,7 @@
|
|||
#include "jit/AtomicOperations.h"
|
||||
#include "jit/InlinableNatives.h"
|
||||
#include "js/Class.h"
|
||||
#include "vm/BigIntType.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/Time.h"
|
||||
#include "vm/TypedArrayObject.h"
|
||||
#include "wasm/WasmInstance.h"
|
||||
|
|
@ -125,68 +121,6 @@ GetTypedArrayIndex(JSContext* cx, HandleValue v, Handle<TypedArrayObject*> view,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsWaitableTypedArray(Scalar::Type viewType)
|
||||
{
|
||||
return viewType == Scalar::Int32 || viewType == Scalar::BigInt64;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
GetWaiterByteOffset(Handle<TypedArrayObject*> view, uint32_t offset)
|
||||
{
|
||||
return view->byteOffset() + offset * TypedArrayElemSize(view->type());
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
BigIntToRawBits(Scalar::Type viewType, BigInt* value)
|
||||
{
|
||||
if (viewType == Scalar::BigInt64)
|
||||
return uint64_t(BigInt::toInt64(value));
|
||||
MOZ_ASSERT(viewType == Scalar::BigUint64);
|
||||
return BigInt::toUint64(value);
|
||||
}
|
||||
|
||||
static bool
|
||||
BigIntToRawBits(JSContext* cx, Scalar::Type viewType, HandleValue value, uint64_t* bits)
|
||||
{
|
||||
MOZ_ASSERT(Scalar::isBigIntType(viewType));
|
||||
|
||||
RootedBigInt bigint(cx, ToBigInt(cx, value));
|
||||
if (!bigint)
|
||||
return false;
|
||||
|
||||
*bits = BigIntToRawBits(viewType, bigint);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetBigIntResult(JSContext* cx, Scalar::Type viewType, uint64_t bits, MutableHandleValue result)
|
||||
{
|
||||
MOZ_ASSERT(Scalar::isBigIntType(viewType));
|
||||
|
||||
BigInt* bigint = viewType == Scalar::BigInt64
|
||||
? BigInt::createFromInt64(cx, mozilla::BitwiseCast<int64_t>(bits))
|
||||
: BigInt::createFromUint64(cx, bits);
|
||||
if (!bigint)
|
||||
return false;
|
||||
|
||||
result.setBigInt(bigint);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
WaitValueMatches(Handle<TypedArrayObject*> view, uint32_t offset, uint64_t expected)
|
||||
{
|
||||
SharedMem<void*> viewData = view->viewDataShared();
|
||||
if (view->type() == Scalar::BigInt64) {
|
||||
return jit::AtomicOperations::loadSafeWhenRacy(viewData.cast<uint64_t*>() + offset) ==
|
||||
expected;
|
||||
}
|
||||
|
||||
return uint32_t(jit::AtomicOperations::loadSafeWhenRacy(viewData.cast<int32_t*>() + offset)) ==
|
||||
uint32_t(expected);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
CompareExchange(Scalar::Type viewType, int32_t oldCandidate, int32_t newCandidate,
|
||||
SharedMem<void*> viewData, uint32_t offset, bool* badArrayType = nullptr)
|
||||
|
|
@ -257,20 +191,6 @@ js::atomics_compareExchange(JSContext* cx, unsigned argc, Value* vp)
|
|||
uint32_t offset;
|
||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||
return false;
|
||||
|
||||
if (Scalar::isBigIntType(view->type())) {
|
||||
uint64_t oldCandidate;
|
||||
if (!BigIntToRawBits(cx, view->type(), oldv, &oldCandidate))
|
||||
return false;
|
||||
uint64_t newCandidate;
|
||||
if (!BigIntToRawBits(cx, view->type(), newv, &newCandidate))
|
||||
return false;
|
||||
|
||||
uint64_t result = jit::AtomicOperations::compareExchangeSeqCst(
|
||||
view->viewDataShared().cast<uint64_t*>() + offset, oldCandidate, newCandidate);
|
||||
return SetBigIntResult(cx, view->type(), result, r);
|
||||
}
|
||||
|
||||
int32_t oldCandidate;
|
||||
if (!ToInt32(cx, oldv, &oldCandidate))
|
||||
return false;
|
||||
|
|
@ -339,22 +259,6 @@ js::atomics_load(JSContext* cx, unsigned argc, Value* vp)
|
|||
r.setNumber(v);
|
||||
return true;
|
||||
}
|
||||
case Scalar::BigInt64: {
|
||||
int64_t v = jit::AtomicOperations::loadSeqCst(viewData.cast<int64_t*>() + offset);
|
||||
BigInt* bigint = BigInt::createFromInt64(cx, v);
|
||||
if (!bigint)
|
||||
return false;
|
||||
r.setBigInt(bigint);
|
||||
return true;
|
||||
}
|
||||
case Scalar::BigUint64: {
|
||||
uint64_t v = jit::AtomicOperations::loadSeqCst(viewData.cast<uint64_t*>() + offset);
|
||||
BigInt* bigint = BigInt::createFromUint64(cx, v);
|
||||
if (!bigint)
|
||||
return false;
|
||||
r.setBigInt(bigint);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return ReportBadArrayType(cx);
|
||||
}
|
||||
|
|
@ -433,25 +337,6 @@ ExchangeOrStore(JSContext* cx, unsigned argc, Value* vp)
|
|||
uint32_t offset;
|
||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||
return false;
|
||||
|
||||
if (Scalar::isBigIntType(view->type())) {
|
||||
RootedBigInt bigint(cx, ToBigInt(cx, valv));
|
||||
if (!bigint)
|
||||
return false;
|
||||
|
||||
uint64_t value = BigIntToRawBits(view->type(), bigint);
|
||||
if (op == DoStore) {
|
||||
jit::AtomicOperations::storeSeqCst(view->viewDataShared().cast<uint64_t*>() + offset,
|
||||
value);
|
||||
r.setBigInt(bigint);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t result = jit::AtomicOperations::exchangeSeqCst(
|
||||
view->viewDataShared().cast<uint64_t*>() + offset, value);
|
||||
return SetBigIntResult(cx, view->type(), result, r);
|
||||
}
|
||||
|
||||
double integerValue;
|
||||
if (!ToInteger(cx, valv, &integerValue))
|
||||
return false;
|
||||
|
|
@ -495,24 +380,6 @@ AtomicsBinop(JSContext* cx, HandleValue objv, HandleValue idxv, HandleValue valv
|
|||
uint32_t offset;
|
||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||
return false;
|
||||
|
||||
if (Scalar::isBigIntType(view->type())) {
|
||||
uint64_t value;
|
||||
if (!BigIntToRawBits(cx, view->type(), valv, &value))
|
||||
return false;
|
||||
|
||||
SharedMem<uint64_t*> addr = view->viewDataShared().cast<uint64_t*>() + offset;
|
||||
uint64_t old = jit::AtomicOperations::loadSeqCst(addr);
|
||||
for (;;) {
|
||||
uint64_t replacement = T::operate64(old, value);
|
||||
uint64_t observed = jit::AtomicOperations::compareExchangeSeqCst(addr, old,
|
||||
replacement);
|
||||
if (observed == old)
|
||||
return SetBigIntResult(cx, view->type(), old, r);
|
||||
old = observed;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t numberValue;
|
||||
if (!ToInt32(cx, valv, &numberValue))
|
||||
return false;
|
||||
|
|
@ -567,7 +434,6 @@ class PerformAdd
|
|||
public:
|
||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchAddSeqCst)
|
||||
static int32_t perform(int32_t x, int32_t y) { return x + y; }
|
||||
static uint64_t operate64(uint64_t x, uint64_t y) { return x + y; }
|
||||
};
|
||||
|
||||
bool
|
||||
|
|
@ -582,7 +448,6 @@ class PerformSub
|
|||
public:
|
||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchSubSeqCst)
|
||||
static int32_t perform(int32_t x, int32_t y) { return x - y; }
|
||||
static uint64_t operate64(uint64_t x, uint64_t y) { return x - y; }
|
||||
};
|
||||
|
||||
bool
|
||||
|
|
@ -597,7 +462,6 @@ class PerformAnd
|
|||
public:
|
||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchAndSeqCst)
|
||||
static int32_t perform(int32_t x, int32_t y) { return x & y; }
|
||||
static uint64_t operate64(uint64_t x, uint64_t y) { return x & y; }
|
||||
};
|
||||
|
||||
bool
|
||||
|
|
@ -612,7 +476,6 @@ class PerformOr
|
|||
public:
|
||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchOrSeqCst)
|
||||
static int32_t perform(int32_t x, int32_t y) { return x | y; }
|
||||
static uint64_t operate64(uint64_t x, uint64_t y) { return x | y; }
|
||||
};
|
||||
|
||||
bool
|
||||
|
|
@ -627,7 +490,6 @@ class PerformXor
|
|||
public:
|
||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchXorSeqCst)
|
||||
static int32_t perform(int32_t x, int32_t y) { return x ^ y; }
|
||||
static uint64_t operate64(uint64_t x, uint64_t y) { return x ^ y; }
|
||||
};
|
||||
|
||||
bool
|
||||
|
|
@ -831,13 +693,11 @@ js::atomics_cmpxchg_asm_callout(wasm::Instance* instance, int32_t vt, int32_t of
|
|||
|
||||
namespace js {
|
||||
|
||||
class AtomicsWaitAsyncTask;
|
||||
|
||||
// Represents one waiting worker.
|
||||
//
|
||||
// The type is declared opaque in SharedArrayObject.h. Instances of
|
||||
// js::FutexWaiter are linked onto a list across a call to FutexRuntime::wait()
|
||||
// or an async wait task.
|
||||
// js::FutexWaiter are stack-allocated and linked onto a list across a
|
||||
// call to FutexRuntime::wait().
|
||||
//
|
||||
// The 'waiters' field of the SharedArrayRawBuffer points to the highest
|
||||
// priority waiter in the list, and lower priority nodes are linked through
|
||||
|
|
@ -851,34 +711,14 @@ class FutexWaiter
|
|||
public:
|
||||
FutexWaiter(uint32_t offset, JSRuntime* rt)
|
||||
: offset(offset),
|
||||
kind(Sync),
|
||||
rt(rt),
|
||||
asyncTask(nullptr),
|
||||
lower_pri(nullptr),
|
||||
back(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
FutexWaiter(uint32_t offset, AtomicsWaitAsyncTask* asyncTask)
|
||||
: offset(offset),
|
||||
kind(Async),
|
||||
rt(nullptr),
|
||||
asyncTask(asyncTask),
|
||||
lower_pri(nullptr),
|
||||
back(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool isWaiting() const;
|
||||
void notify();
|
||||
|
||||
uint32_t offset; // byte offset within the SharedArrayBuffer
|
||||
enum WaiterKind {
|
||||
Sync,
|
||||
Async
|
||||
} kind;
|
||||
uint32_t offset; // int32 element index within the SharedArrayBuffer
|
||||
JSRuntime* rt; // The runtime of the waiter
|
||||
AtomicsWaitAsyncTask* asyncTask; // The async waiter task, if any
|
||||
FutexWaiter* lower_pri; // Lower priority nodes in circular doubly-linked list of waiters
|
||||
FutexWaiter* back; // Other direction
|
||||
};
|
||||
|
|
@ -902,195 +742,8 @@ class AutoLockFutexAPI
|
|||
js::UniqueLock<js::Mutex>& unique() { return *unique_; }
|
||||
};
|
||||
|
||||
static void
|
||||
AddWaiter(SharedArrayRawBuffer* sarb, FutexWaiter* waiter)
|
||||
{
|
||||
if (FutexWaiter* waiters = sarb->waiters()) {
|
||||
waiter->lower_pri = waiters;
|
||||
waiter->back = waiters->back;
|
||||
waiters->back->lower_pri = waiter;
|
||||
waiters->back = waiter;
|
||||
} else {
|
||||
waiter->lower_pri = waiter->back = waiter;
|
||||
sarb->setWaiters(waiter);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveWaiter(SharedArrayRawBuffer* sarb, FutexWaiter* waiter)
|
||||
{
|
||||
if (waiter->lower_pri == waiter) {
|
||||
sarb->setWaiters(nullptr);
|
||||
} else {
|
||||
waiter->lower_pri->back = waiter->back;
|
||||
waiter->back->lower_pri = waiter->lower_pri;
|
||||
if (sarb->waiters() == waiter)
|
||||
sarb->setWaiters(waiter->lower_pri);
|
||||
}
|
||||
waiter->lower_pri = nullptr;
|
||||
waiter->back = nullptr;
|
||||
}
|
||||
|
||||
class AtomicsWaitAsyncTask : public PromiseTask
|
||||
{
|
||||
enum class State {
|
||||
Waiting,
|
||||
Notified,
|
||||
TimedOut
|
||||
};
|
||||
|
||||
SharedArrayRawBuffer* sarb_;
|
||||
FutexWaiter waiter_;
|
||||
mozilla::Maybe<mozilla::TimeDuration> timeout_;
|
||||
ConditionVariable cond_;
|
||||
State state_;
|
||||
bool isInWaiterList_;
|
||||
|
||||
public:
|
||||
AtomicsWaitAsyncTask(JSContext* cx, Handle<PromiseObject*> promise,
|
||||
SharedArrayRawBuffer* sarb, uint32_t offset,
|
||||
mozilla::Maybe<mozilla::TimeDuration>& timeout)
|
||||
: PromiseTask(cx, promise),
|
||||
sarb_(sarb),
|
||||
waiter_(offset, this),
|
||||
timeout_(timeout),
|
||||
state_(State::Waiting),
|
||||
isInWaiterList_(false)
|
||||
{
|
||||
}
|
||||
|
||||
~AtomicsWaitAsyncTask() {
|
||||
if (isInWaiterList_) {
|
||||
AutoLockFutexAPI lock;
|
||||
if (isInWaiterList_)
|
||||
removeFromWaiterList();
|
||||
}
|
||||
sarb_->dropReference();
|
||||
}
|
||||
|
||||
FutexWaiter* waiter() {
|
||||
return &waiter_;
|
||||
}
|
||||
|
||||
void setInWaiterList() {
|
||||
isInWaiterList_ = true;
|
||||
}
|
||||
|
||||
bool isWaiting() const {
|
||||
return state_ == State::Waiting;
|
||||
}
|
||||
|
||||
void notify() {
|
||||
MOZ_ASSERT(isWaiting());
|
||||
state_ = State::Notified;
|
||||
cond_.notify_all();
|
||||
}
|
||||
|
||||
void execute() override {
|
||||
AutoLockFutexAPI lock;
|
||||
|
||||
const bool isTimed = timeout_.isSome();
|
||||
auto finalEnd = timeout_.map([](mozilla::TimeDuration& timeout) {
|
||||
return mozilla::TimeStamp::Now() + timeout;
|
||||
});
|
||||
auto maxSlice = mozilla::TimeDuration::FromSeconds(4000.0);
|
||||
|
||||
while (state_ == State::Waiting) {
|
||||
if (isTimed) {
|
||||
auto sliceEnd = finalEnd.map([&](mozilla::TimeStamp& finalEnd) {
|
||||
auto sliceEnd = mozilla::TimeStamp::Now() + maxSlice;
|
||||
if (finalEnd < sliceEnd)
|
||||
sliceEnd = finalEnd;
|
||||
return sliceEnd;
|
||||
});
|
||||
|
||||
mozilla::Unused << cond_.wait_until(lock.unique(), *sliceEnd);
|
||||
if (state_ == State::Waiting && mozilla::TimeStamp::Now() >= *finalEnd) {
|
||||
state_ = State::TimedOut;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cond_.wait(lock.unique());
|
||||
}
|
||||
}
|
||||
|
||||
if (isInWaiterList_)
|
||||
removeFromWaiterList();
|
||||
}
|
||||
|
||||
private:
|
||||
void removeFromWaiterList() {
|
||||
MOZ_ASSERT(isInWaiterList_);
|
||||
RemoveWaiter(sarb_, &waiter_);
|
||||
isInWaiterList_ = false;
|
||||
}
|
||||
|
||||
bool finishPromise(JSContext* cx, Handle<PromiseObject*> promise) override {
|
||||
RootedValue result(cx);
|
||||
if (state_ == State::TimedOut)
|
||||
result.setString(cx->names().futexTimedOut);
|
||||
else
|
||||
result.setString(cx->names().futexOK);
|
||||
return PromiseObject::resolve(cx, promise, result);
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
FutexWaiter::isWaiting() const
|
||||
{
|
||||
if (kind == Sync)
|
||||
return rt->fx.isWaiting();
|
||||
return asyncTask->isWaiting();
|
||||
}
|
||||
|
||||
void
|
||||
FutexWaiter::notify()
|
||||
{
|
||||
if (kind == Sync) {
|
||||
rt->fx.notify(FutexRuntime::NotifyExplicit);
|
||||
return;
|
||||
}
|
||||
asyncTask->notify();
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
static bool
|
||||
GetWaitTimeout(JSContext* cx, HandleValue timeoutv,
|
||||
mozilla::Maybe<mozilla::TimeDuration>* timeout)
|
||||
{
|
||||
timeout->reset();
|
||||
if (!timeoutv.isUndefined()) {
|
||||
double timeout_ms;
|
||||
if (!ToNumber(cx, timeoutv, &timeout_ms))
|
||||
return false;
|
||||
if (!mozilla::IsNaN(timeout_ms)) {
|
||||
if (timeout_ms < 0)
|
||||
*timeout = mozilla::Some(mozilla::TimeDuration::FromSeconds(0.0));
|
||||
else if (!mozilla::IsInfinite(timeout_ms))
|
||||
*timeout = mozilla::Some(mozilla::TimeDuration::FromMilliseconds(timeout_ms));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CreateWaitAsyncResult(JSContext* cx, bool isAsync, HandleValue value, MutableHandleValue rval)
|
||||
{
|
||||
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
RootedValue asyncValue(cx, BooleanValue(isAsync));
|
||||
if (!NativeDefineDataProperty(cx, obj, cx->names().async, asyncValue, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
if (!NativeDefineDataProperty(cx, obj, cx->names().value, value, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
|
||||
rval.setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
|
@ -1106,24 +759,26 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
|
|||
Rooted<TypedArrayObject*> view(cx, nullptr);
|
||||
if (!GetSharedTypedArray(cx, objv, &view))
|
||||
return false;
|
||||
if (!IsWaitableTypedArray(view->type()))
|
||||
if (view->type() != Scalar::Int32)
|
||||
return ReportBadArrayType(cx);
|
||||
uint32_t offset;
|
||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||
return false;
|
||||
uint64_t value = 0;
|
||||
if (view->type() == Scalar::BigInt64) {
|
||||
if (!BigIntToRawBits(cx, view->type(), valv, &value))
|
||||
return false;
|
||||
} else {
|
||||
int32_t int32Value;
|
||||
if (!ToInt32(cx, valv, &int32Value))
|
||||
return false;
|
||||
value = uint32_t(int32Value);
|
||||
}
|
||||
mozilla::Maybe<mozilla::TimeDuration> timeout;
|
||||
if (!GetWaitTimeout(cx, timeoutv, &timeout))
|
||||
int32_t value;
|
||||
if (!ToInt32(cx, valv, &value))
|
||||
return false;
|
||||
mozilla::Maybe<mozilla::TimeDuration> timeout;
|
||||
if (!timeoutv.isUndefined()) {
|
||||
double timeout_ms;
|
||||
if (!ToNumber(cx, timeoutv, &timeout_ms))
|
||||
return false;
|
||||
if (!mozilla::IsNaN(timeout_ms)) {
|
||||
if (timeout_ms < 0)
|
||||
timeout = mozilla::Some(mozilla::TimeDuration::FromSeconds(0.0));
|
||||
else if (!mozilla::IsInfinite(timeout_ms))
|
||||
timeout = mozilla::Some(mozilla::TimeDuration::FromMilliseconds(timeout_ms));
|
||||
}
|
||||
}
|
||||
|
||||
if (!rt->fx.canWait())
|
||||
return ReportCannotWait(cx);
|
||||
|
|
@ -1132,7 +787,8 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
|
|||
// and it provides the necessary memory fence.
|
||||
AutoLockFutexAPI lock;
|
||||
|
||||
if (!WaitValueMatches(view, offset, value)) {
|
||||
SharedMem<int32_t*> addr = view->viewDataShared().cast<int32_t*>() + offset;
|
||||
if (jit::AtomicOperations::loadSafeWhenRacy(addr) != value) {
|
||||
r.setString(cx->names().futexNotEqual);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1140,8 +796,16 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
|
|||
Rooted<SharedArrayBufferObject*> sab(cx, view->bufferShared());
|
||||
SharedArrayRawBuffer* sarb = sab->rawBufferObject();
|
||||
|
||||
FutexWaiter w(GetWaiterByteOffset(view, offset), rt);
|
||||
AddWaiter(sarb, &w);
|
||||
FutexWaiter w(offset, rt);
|
||||
if (FutexWaiter* waiters = sarb->waiters()) {
|
||||
w.lower_pri = waiters;
|
||||
w.back = waiters->back;
|
||||
waiters->back->lower_pri = &w;
|
||||
waiters->back = &w;
|
||||
} else {
|
||||
w.lower_pri = w.back = &w;
|
||||
sarb->setWaiters(&w);
|
||||
}
|
||||
|
||||
FutexRuntime::WaitResult result = FutexRuntime::FutexOK;
|
||||
bool retval = rt->fx.wait(cx, lock.unique(), timeout, &result);
|
||||
|
|
@ -1156,96 +820,15 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
}
|
||||
|
||||
RemoveWaiter(sarb, &w);
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
js::atomics_waitAsync(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
HandleValue objv = args.get(0);
|
||||
HandleValue idxv = args.get(1);
|
||||
HandleValue valv = args.get(2);
|
||||
HandleValue timeoutv = args.get(3);
|
||||
MutableHandleValue r = args.rval();
|
||||
|
||||
Rooted<TypedArrayObject*> view(cx, nullptr);
|
||||
if (!GetSharedTypedArray(cx, objv, &view))
|
||||
return false;
|
||||
if (!IsWaitableTypedArray(view->type()))
|
||||
return ReportBadArrayType(cx);
|
||||
uint32_t offset;
|
||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||
return false;
|
||||
uint64_t value = 0;
|
||||
if (view->type() == Scalar::BigInt64) {
|
||||
if (!BigIntToRawBits(cx, view->type(), valv, &value))
|
||||
return false;
|
||||
if (w.lower_pri == &w) {
|
||||
sarb->setWaiters(nullptr);
|
||||
} else {
|
||||
int32_t int32Value;
|
||||
if (!ToInt32(cx, valv, &int32Value))
|
||||
return false;
|
||||
value = uint32_t(int32Value);
|
||||
w.lower_pri->back = w.back;
|
||||
w.back->lower_pri = w.lower_pri;
|
||||
if (sarb->waiters() == &w)
|
||||
sarb->setWaiters(w.lower_pri);
|
||||
}
|
||||
mozilla::Maybe<mozilla::TimeDuration> timeout;
|
||||
if (!GetWaitTimeout(cx, timeoutv, &timeout))
|
||||
return false;
|
||||
|
||||
Rooted<PromiseObject*> promise(cx, PromiseObject::createSkippingExecutor(cx));
|
||||
if (!promise)
|
||||
return false;
|
||||
|
||||
RootedValue promiseValue(cx, ObjectValue(*promise));
|
||||
RootedValue result(cx);
|
||||
if (!CreateWaitAsyncResult(cx, true, promiseValue, &result))
|
||||
return false;
|
||||
|
||||
Rooted<SharedArrayBufferObject*> sab(cx, view->bufferShared());
|
||||
SharedArrayRawBuffer* sarb = sab->rawBufferObject();
|
||||
if (!sarb->addReference()) {
|
||||
JS_ReportErrorASCII(cx, "Reference count overflow on SharedArrayBuffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto task = cx->make_unique<AtomicsWaitAsyncTask>(cx, promise, sarb, offset, timeout);
|
||||
if (!task) {
|
||||
sarb->dropReference();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isAsync = false;
|
||||
RootedValue immediateResult(cx);
|
||||
{
|
||||
AutoLockFutexAPI lock;
|
||||
|
||||
if (!WaitValueMatches(view, offset, value)) {
|
||||
immediateResult.setString(cx->names().futexNotEqual);
|
||||
} else if (timeout.isSome() && timeout->ToMilliseconds() == 0.0) {
|
||||
immediateResult.setString(cx->names().futexTimedOut);
|
||||
} else {
|
||||
if (!cx->startAsyncTaskCallback || !cx->finishAsyncTaskCallback ||
|
||||
!CanUseExtraThreads())
|
||||
{
|
||||
JS_ReportErrorASCII(cx, "Atomics.waitAsync not supported in this runtime.");
|
||||
return false;
|
||||
}
|
||||
|
||||
task->waiter()->offset = GetWaiterByteOffset(view, offset);
|
||||
AddWaiter(sarb, task->waiter());
|
||||
task->setInWaiterList();
|
||||
isAsync = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAsync)
|
||||
return CreateWaitAsyncResult(cx, false, immediateResult, r);
|
||||
|
||||
if (!StartPromiseTask(cx, Move(task)))
|
||||
return false;
|
||||
|
||||
r.set(result);
|
||||
return true;
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -1260,12 +843,11 @@ js::atomics_notify(JSContext* cx, unsigned argc, Value* vp)
|
|||
Rooted<TypedArrayObject*> view(cx, nullptr);
|
||||
if (!GetSharedTypedArray(cx, objv, &view))
|
||||
return false;
|
||||
if (!IsWaitableTypedArray(view->type()))
|
||||
if (view->type() != Scalar::Int32)
|
||||
return ReportBadArrayType(cx);
|
||||
uint32_t offset;
|
||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||
return false;
|
||||
offset = GetWaiterByteOffset(view, offset);
|
||||
double count;
|
||||
if (countv.isUndefined()) {
|
||||
count = mozilla::PositiveInfinity<double>();
|
||||
|
|
@ -1288,9 +870,9 @@ js::atomics_notify(JSContext* cx, unsigned argc, Value* vp)
|
|||
do {
|
||||
FutexWaiter* c = iter;
|
||||
iter = iter->lower_pri;
|
||||
if (c->offset != offset || !c->isWaiting())
|
||||
if (c->offset != offset || !c->rt->fx.isWaiting())
|
||||
continue;
|
||||
c->notify();
|
||||
c->rt->fx.notify(FutexRuntime::NotifyExplicit);
|
||||
++woken;
|
||||
--count;
|
||||
} while (count > 0 && iter != waiters);
|
||||
|
|
@ -1524,7 +1106,6 @@ const JSFunctionSpec AtomicsMethods[] = {
|
|||
JS_INLINABLE_FN("xor", atomics_xor, 3,0, AtomicsXor),
|
||||
JS_INLINABLE_FN("isLockFree", atomics_isLockFree, 1,0, AtomicsIsLockFree),
|
||||
JS_FN("wait", atomics_wait, 4,0),
|
||||
JS_FN("waitAsync", atomics_waitAsync, 4,0),
|
||||
JS_FN("notify", atomics_notify, 3,0),
|
||||
JS_FN("wake", atomics_notify, 3,0), //Legacy name
|
||||
JS_FS_END
|
||||
|
|
|
|||
|
|
@ -24,19 +24,18 @@ class AtomicsObject : public JSObject
|
|||
static MOZ_MUST_USE bool toString(JSContext* cx, unsigned int argc, Value* vp);
|
||||
};
|
||||
|
||||
[[nodiscard]] bool atomics_compareExchange(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_exchange(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_load(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_store(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_add(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_sub(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_and(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_or(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_xor(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_wait(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_waitAsync(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] bool atomics_notify(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_compareExchange(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_exchange(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_load(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_store(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_add(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_sub(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_and(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_or(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_xor(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_wait(JSContext* cx, unsigned argc, Value* vp);
|
||||
MOZ_MUST_USE bool atomics_notify(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
/* asm.js callouts */
|
||||
namespace wasm { class Instance; }
|
||||
|
|
|
|||
|
|
@ -55,49 +55,6 @@ function MapForEach(callbackfn, thisArg = undefined) {
|
|||
}
|
||||
}
|
||||
|
||||
// ES2024
|
||||
// Map.groupBy ( items, callbackfn )
|
||||
function MapGroupBy(items, callbackfn) {
|
||||
// Step 1.
|
||||
RequireObjectCoercible(items);
|
||||
|
||||
// Step 2.
|
||||
if (!IsCallable(callbackfn))
|
||||
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn));
|
||||
|
||||
// Step 3.
|
||||
var groups = std_Map_create();
|
||||
|
||||
// Step 4.
|
||||
var k = 0;
|
||||
|
||||
// Steps 5-8.
|
||||
for (var value of allowContentIter(items)) {
|
||||
// Step 6.a.
|
||||
if (k >= MAX_NUMERIC_INDEX)
|
||||
ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
|
||||
|
||||
// Step 6.b.
|
||||
var key = callContentFunction(callbackfn, undefined, value, k);
|
||||
|
||||
// Steps 6.c-d.
|
||||
var elements;
|
||||
if (callFunction(std_Map_has, groups, key)) {
|
||||
elements = callFunction(std_Map_get, groups, key);
|
||||
callFunction(std_Array_push, elements, value);
|
||||
} else {
|
||||
elements = [value];
|
||||
callFunction(std_Map_set, groups, key, elements);
|
||||
}
|
||||
|
||||
// Step 6.e.
|
||||
k++;
|
||||
}
|
||||
|
||||
// Step 9.
|
||||
return groups;
|
||||
}
|
||||
|
||||
var iteratorTemp = { mapIterationResultPair : null };
|
||||
|
||||
function MapIteratorNext() {
|
||||
|
|
|
|||
|
|
@ -332,15 +332,9 @@ const JSPropertySpec MapObject::staticProperties[] = {
|
|||
JS_PS_END
|
||||
};
|
||||
|
||||
const JSFunctionSpec MapObject::staticMethods[] = {
|
||||
JS_SELF_HOSTED_FN("groupBy", "MapGroupBy", 2, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static JSObject*
|
||||
InitClass(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp, JSProtoKey key, Native construct,
|
||||
const JSPropertySpec* properties, const JSFunctionSpec* methods,
|
||||
const JSFunctionSpec* staticMethods,
|
||||
const JSPropertySpec* staticProperties)
|
||||
{
|
||||
RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
|
|
@ -349,13 +343,8 @@ InitClass(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp, JSPro
|
|||
|
||||
Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0));
|
||||
if (!ctor ||
|
||||
!JS_DefineProperties(cx, ctor, staticProperties))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
if (staticMethods && !JS_DefineFunctions(cx, ctor, staticMethods))
|
||||
return nullptr;
|
||||
if (!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
||||
!JS_DefineProperties(cx, ctor, staticProperties) ||
|
||||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
||||
!DefinePropertiesAndFunctions(cx, proto, properties, methods) ||
|
||||
!GlobalObject::initBuiltinConstructor(cx, global, key, ctor, proto))
|
||||
{
|
||||
|
|
@ -370,7 +359,7 @@ MapObject::initClass(JSContext* cx, JSObject* obj)
|
|||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
RootedObject proto(cx,
|
||||
InitClass(cx, global, &class_, JSProto_Map, construct, properties, methods,
|
||||
staticMethods, staticProperties));
|
||||
staticProperties));
|
||||
if (proto) {
|
||||
// Define the "entries" method.
|
||||
JSFunction* fun = JS_DefineFunction(cx, proto, "entries", entries, 0, 0);
|
||||
|
|
@ -1095,7 +1084,7 @@ SetObject::initClass(JSContext* cx, JSObject* obj)
|
|||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
RootedObject proto(cx,
|
||||
InitClass(cx, global, &class_, JSProto_Set, construct, properties, methods,
|
||||
nullptr, staticProperties));
|
||||
staticProperties));
|
||||
if (proto) {
|
||||
// Define the "values" method.
|
||||
JSFunction* fun = JS_DefineFunction(cx, proto, "values", values, 0, 0);
|
||||
|
|
|
|||
|
|
@ -109,10 +109,8 @@ class MapObject : public NativeObject {
|
|||
|
||||
static MOZ_MUST_USE bool getKeysAndValuesInterleaved(JSContext* cx, HandleObject obj,
|
||||
JS::MutableHandle<GCVector<JS::Value>> entries);
|
||||
[[nodiscard]] static bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool get(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool set(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MapObject* create(JSContext* cx, HandleObject proto = nullptr);
|
||||
|
||||
// Publicly exposed Map calls for JSAPI access (webidl maplike/setlike
|
||||
|
|
@ -139,7 +137,6 @@ class MapObject : public NativeObject {
|
|||
|
||||
static const JSPropertySpec properties[];
|
||||
static const JSFunctionSpec methods[];
|
||||
static const JSFunctionSpec staticMethods[];
|
||||
static const JSPropertySpec staticProperties[];
|
||||
ValueMap* getData() { return static_cast<ValueMap*>(getPrivate()); }
|
||||
static ValueMap& extract(HandleObject o);
|
||||
|
|
@ -153,20 +150,22 @@ class MapObject : public NativeObject {
|
|||
|
||||
static MOZ_MUST_USE bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind);
|
||||
|
||||
[[nodiscard]] static bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool get_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool set_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool keys_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool keys(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||
[[nodiscard]] static bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
[[nodiscard]] static bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool size_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool get_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool get(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool has_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool set_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool set(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool keys_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool keys(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool values_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
class MapIteratorObject : public NativeObject
|
||||
|
|
|
|||
|
|
@ -240,16 +240,12 @@ function ObjectGroupBy(items, callbackfn) {
|
|||
// Steps 5-8.
|
||||
for (var value of allowContentIter(items)) {
|
||||
// Step 6.a.
|
||||
if (k >= MAX_NUMERIC_INDEX)
|
||||
ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
|
||||
|
||||
// Step 6.b.
|
||||
var key = callContentFunction(callbackfn, undefined, value, k);
|
||||
|
||||
// Step 6.c.
|
||||
// Step 6.b.
|
||||
key = ToPropertyKey(key);
|
||||
|
||||
// Steps 6.d-e.
|
||||
// Steps 6.c-d.
|
||||
var elements = groups[key];
|
||||
if (elements === undefined) {
|
||||
_DefineDataProperty(groups, key, [value]);
|
||||
|
|
@ -257,7 +253,7 @@ function ObjectGroupBy(items, callbackfn) {
|
|||
callFunction(std_Array_push, elements, value);
|
||||
}
|
||||
|
||||
// Step 6.f.
|
||||
// Step 6.e.
|
||||
k++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3673,48 +3673,6 @@ Promise_static_resolve(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
// ES2024
|
||||
// Promise.withResolvers ( )
|
||||
static bool
|
||||
Promise_static_withResolvers(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
if (!args.thisv().isObject()) {
|
||||
ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, -1, args.thisv(), nullptr);
|
||||
return false;
|
||||
}
|
||||
RootedObject C(cx, &args.thisv().toObject());
|
||||
|
||||
// Step 2.
|
||||
Rooted<PromiseCapability> capability(cx);
|
||||
if (!NewPromiseCapability(cx, C, &capability, false))
|
||||
return false;
|
||||
|
||||
// Step 3.
|
||||
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
// Steps 4-7.
|
||||
RootedValue promise(cx, ObjectValue(*capability.promise()));
|
||||
if (!::JS_DefineProperty(cx, obj, "promise", promise, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
|
||||
RootedValue resolve(cx, ObjectValue(*capability.resolve()));
|
||||
if (!::JS_DefineProperty(cx, obj, "resolve", resolve, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
|
||||
RootedValue reject(cx, ObjectValue(*capability.reject()));
|
||||
if (!::JS_DefineProperty(cx, obj, "reject", reject, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
|
||||
// Step 8.
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unforgeable version of ES2016, 25.4.4.5, Promise.resolve.
|
||||
*/
|
||||
|
|
@ -5222,7 +5180,6 @@ static const JSFunctionSpec promise_static_methods[] = {
|
|||
JS_FN("race", Promise_static_race, 1, 0),
|
||||
JS_FN("reject", Promise_reject, 1, 0),
|
||||
JS_FN("resolve", Promise_static_resolve, 1, 0),
|
||||
JS_FN("withResolvers", Promise_static_withResolvers, 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -165,8 +165,6 @@ class CountQueuingStrategy : public NativeObject
|
|||
static const Class protoClass_;
|
||||
};
|
||||
|
||||
[[nodiscard]] bool InitStreamExtras(JSContext* cx, HandleObject global);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* builtin_Stream_h */
|
||||
|
|
|
|||
|
|
@ -654,82 +654,6 @@ function String_repeat(count) {
|
|||
return T;
|
||||
}
|
||||
|
||||
// ES2024
|
||||
// String.prototype.isWellFormed ( )
|
||||
function String_isWellFormed() {
|
||||
// Steps 1-2.
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
|
||||
// Step 3.
|
||||
var length = S.length;
|
||||
for (var k = 0; k < length; k++) {
|
||||
var c = callFunction(std_String_charCodeAt, S, k);
|
||||
if (c >= 0xD800 && c <= 0xDBFF) {
|
||||
if (k + 1 >= length)
|
||||
return false;
|
||||
|
||||
var d = callFunction(std_String_charCodeAt, S, k + 1);
|
||||
if (d < 0xDC00 || d > 0xDFFF)
|
||||
return false;
|
||||
|
||||
k++;
|
||||
} else if (c >= 0xDC00 && c <= 0xDFFF) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
return true;
|
||||
}
|
||||
|
||||
// ES2024
|
||||
// String.prototype.toWellFormed ( )
|
||||
function String_toWellFormed() {
|
||||
// Steps 1-2.
|
||||
RequireObjectCoercible(this);
|
||||
var S = ToString(this);
|
||||
|
||||
// Step 3.
|
||||
var length = S.length;
|
||||
var result = "";
|
||||
var copied = 0;
|
||||
|
||||
for (var k = 0; k < length; k++) {
|
||||
var c = callFunction(std_String_charCodeAt, S, k);
|
||||
var isUnpairedSurrogate = false;
|
||||
|
||||
if (c >= 0xD800 && c <= 0xDBFF) {
|
||||
if (k + 1 < length) {
|
||||
var d = callFunction(std_String_charCodeAt, S, k + 1);
|
||||
if (d >= 0xDC00 && d <= 0xDFFF) {
|
||||
k++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
isUnpairedSurrogate = true;
|
||||
} else if (c >= 0xDC00 && c <= 0xDFFF) {
|
||||
isUnpairedSurrogate = true;
|
||||
}
|
||||
|
||||
if (isUnpairedSurrogate) {
|
||||
if (copied < k)
|
||||
result += callFunction(String_substring, S, copied, k);
|
||||
result += "\uFFFD";
|
||||
copied = k + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (copied === 0)
|
||||
return S;
|
||||
|
||||
if (copied < length)
|
||||
result += callFunction(String_substring, S, copied, length);
|
||||
|
||||
// Step 4.
|
||||
return result;
|
||||
}
|
||||
|
||||
// ES6 draft specification, section 21.1.3.27, version 2013-09-27.
|
||||
function String_iterator() {
|
||||
RequireObjectCoercible(this);
|
||||
|
|
|
|||
|
|
@ -37,25 +37,10 @@ function TypedArrayLengthMethod() {
|
|||
return TypedArrayLength(this);
|
||||
}
|
||||
|
||||
function TypedArrayContentTypeIsBigIntMethod() {
|
||||
return IsBigInt64TypedArray(this) || IsBigUint64TypedArray(this);
|
||||
}
|
||||
|
||||
function ThrowIfTypedArrayOutOfBounds(tarray) {
|
||||
if (TypedArrayIsOutOfBounds(tarray))
|
||||
ThrowTypeError(JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||
}
|
||||
|
||||
function ThrowIfPossiblyWrappedTypedArrayOutOfBounds(tarray) {
|
||||
if (PossiblyWrappedTypedArrayIsOutOfBounds(tarray))
|
||||
ThrowTypeError(JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||
}
|
||||
|
||||
function GetAttachedArrayBuffer(tarray) {
|
||||
var buffer = ViewedArrayBufferIfReified(tarray);
|
||||
if (IsDetachedBuffer(buffer))
|
||||
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
|
||||
ThrowIfTypedArrayOutOfBounds(tarray);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
@ -75,13 +60,6 @@ function IsTypedArrayEnsuringArrayBuffer(arg) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (IsObject(arg) && IsPossiblyWrappedTypedArray(arg)) {
|
||||
if (PossiblyWrappedTypedArrayHasDetachedBuffer(arg))
|
||||
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
|
||||
ThrowIfPossiblyWrappedTypedArrayOutOfBounds(arg);
|
||||
return false;
|
||||
}
|
||||
|
||||
callFunction(CallTypedArrayMethodIfWrapped, arg, "GetAttachedArrayBufferMethod");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -101,7 +79,6 @@ function ValidateTypedArray(obj, error) {
|
|||
if (IsPossiblyWrappedTypedArray(obj)) {
|
||||
if (PossiblyWrappedTypedArrayHasDetachedBuffer(obj))
|
||||
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
|
||||
ThrowIfPossiblyWrappedTypedArrayOutOfBounds(obj);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1047,18 +1024,12 @@ function TypedArraySet(overloaded, offset = 0) {
|
|||
// Steps 9-10.
|
||||
var targetBuffer = GetAttachedArrayBuffer(target);
|
||||
|
||||
ThrowIfTypedArrayOutOfBounds(target);
|
||||
|
||||
// Step 11.
|
||||
var targetLength = TypedArrayLength(target);
|
||||
|
||||
// Steps 12 et seq.
|
||||
if (IsPossiblyWrappedTypedArray(overloaded)) {
|
||||
if (PossiblyWrappedTypedArrayHasDetachedBuffer(overloaded))
|
||||
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
|
||||
ThrowIfPossiblyWrappedTypedArrayOutOfBounds(overloaded);
|
||||
if (IsPossiblyWrappedTypedArray(overloaded))
|
||||
return SetFromTypedArray(target, overloaded, targetOffset, targetLength);
|
||||
}
|
||||
|
||||
return SetFromNonTypedArray(target, overloaded, targetOffset, targetLength, targetBuffer);
|
||||
}
|
||||
|
|
@ -1395,8 +1366,6 @@ function TypedArraySubarray(begin, end) {
|
|||
"TypedArraySubarray");
|
||||
}
|
||||
|
||||
GetAttachedArrayBuffer(obj);
|
||||
|
||||
// Steps 4-6.
|
||||
var buffer = TypedArrayBuffer(obj);
|
||||
var srcLength = TypedArrayLength(obj);
|
||||
|
|
@ -1877,10 +1846,7 @@ function ArrayBufferSlice(start, end) {
|
|||
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
|
||||
|
||||
// Steps 19-21.
|
||||
var currentLen = ArrayBufferByteLength(O);
|
||||
var copyLen = first >= currentLen ? 0 : std_Math_min(newLen, currentLen - first);
|
||||
if (copyLen > 0)
|
||||
ArrayBufferCopyData(new_, 0, O, first | 0, copyLen | 0, isWrapped);
|
||||
ArrayBufferCopyData(new_, 0, O, first | 0, newLen | 0, isWrapped);
|
||||
|
||||
// Step 22.
|
||||
return new_;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "builtin/WeakRefObject.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
|
||||
#include "vm/Interpreter-inl.h"
|
||||
|
|
@ -22,80 +21,21 @@ IsWeakMap(HandleValue v)
|
|||
return v.isObject() && v.toObject().is<WeakMapObject>();
|
||||
}
|
||||
|
||||
struct WeakMapObject::Data
|
||||
{
|
||||
ObjectValueMap objectMap;
|
||||
SymbolValueMap symbolMap;
|
||||
|
||||
Data(JSContext* cx, JSObject* owner)
|
||||
: objectMap(cx, owner),
|
||||
symbolMap(cx, owner)
|
||||
{}
|
||||
|
||||
bool init() {
|
||||
return objectMap.init() && symbolMap.init();
|
||||
}
|
||||
};
|
||||
|
||||
ObjectValueMap*
|
||||
WeakMapObject::getMap()
|
||||
{
|
||||
Data* data = getData();
|
||||
return data ? &data->objectMap : nullptr;
|
||||
}
|
||||
|
||||
SymbolValueMap*
|
||||
WeakMapObject::getSymbolMap()
|
||||
{
|
||||
Data* data = getData();
|
||||
return data ? &data->symbolMap : nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
EnsureWeakMapData(JSContext* cx, Handle<WeakMapObject*> mapObj)
|
||||
{
|
||||
if (mapObj->getData())
|
||||
return true;
|
||||
|
||||
auto data = cx->make_unique<WeakMapObject::Data>(cx, mapObj.get());
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
if (!data->init()) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
mapObj->setPrivate(data.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
WeakMap_has_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsWeakMap(args.thisv()));
|
||||
|
||||
if (!CanBeHeldWeakly(args.get(0))) {
|
||||
if (!args.get(0).isObject()) {
|
||||
args.rval().setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
WeakMapObject& weakMap = args.thisv().toObject().as<WeakMapObject>();
|
||||
if (args.get(0).isObject()) {
|
||||
if (ObjectValueMap* map = weakMap.getMap()) {
|
||||
JSObject* key = &args[0].toObject();
|
||||
if (map->has(key)) {
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (SymbolValueMap* map = weakMap.getSymbolMap()) {
|
||||
JS::Symbol* key = args[0].toSymbol();
|
||||
if (map->has(key)) {
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
if (ObjectValueMap* map = args.thisv().toObject().as<WeakMapObject>().getMap()) {
|
||||
JSObject* key = &args[0].toObject();
|
||||
if (map->has(key)) {
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -115,27 +55,16 @@ WeakMap_get_impl(JSContext* cx, const CallArgs& args)
|
|||
{
|
||||
MOZ_ASSERT(IsWeakMap(args.thisv()));
|
||||
|
||||
if (!CanBeHeldWeakly(args.get(0))) {
|
||||
if (!args.get(0).isObject()) {
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
WeakMapObject& weakMap = args.thisv().toObject().as<WeakMapObject>();
|
||||
if (args.get(0).isObject()) {
|
||||
if (ObjectValueMap* map = weakMap.getMap()) {
|
||||
JSObject* key = &args[0].toObject();
|
||||
if (ObjectValueMap::Ptr ptr = map->lookup(key)) {
|
||||
args.rval().set(ptr->value());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (SymbolValueMap* map = weakMap.getSymbolMap()) {
|
||||
JS::Symbol* key = args[0].toSymbol();
|
||||
if (SymbolValueMap::Ptr ptr = map->lookup(key)) {
|
||||
args.rval().set(ptr->value());
|
||||
return true;
|
||||
}
|
||||
if (ObjectValueMap* map = args.thisv().toObject().as<WeakMapObject>().getMap()) {
|
||||
JSObject* key = &args[0].toObject();
|
||||
if (ObjectValueMap::Ptr ptr = map->lookup(key)) {
|
||||
args.rval().set(ptr->value());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,29 +84,17 @@ WeakMap_delete_impl(JSContext* cx, const CallArgs& args)
|
|||
{
|
||||
MOZ_ASSERT(IsWeakMap(args.thisv()));
|
||||
|
||||
if (!CanBeHeldWeakly(args.get(0))) {
|
||||
if (!args.get(0).isObject()) {
|
||||
args.rval().setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
WeakMapObject& weakMap = args.thisv().toObject().as<WeakMapObject>();
|
||||
if (args.get(0).isObject()) {
|
||||
if (ObjectValueMap* map = weakMap.getMap()) {
|
||||
JSObject* key = &args[0].toObject();
|
||||
if (ObjectValueMap::Ptr ptr = map->lookup(key)) {
|
||||
map->remove(ptr);
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (SymbolValueMap* map = weakMap.getSymbolMap()) {
|
||||
JS::Symbol* key = args[0].toSymbol();
|
||||
if (SymbolValueMap::Ptr ptr = map->lookup(key)) {
|
||||
map->remove(ptr);
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
if (ObjectValueMap* map = args.thisv().toObject().as<WeakMapObject>().getMap()) {
|
||||
JSObject* key = &args[0].toObject();
|
||||
if (ObjectValueMap::Ptr ptr = map->lookup(key)) {
|
||||
map->remove(ptr);
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,13 +126,22 @@ TryPreserveReflector(JSContext* cx, HandleObject obj)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetWeakMapObjectEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj,
|
||||
HandleObject key, HandleValue value)
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
SetWeakMapEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj,
|
||||
HandleObject key, HandleValue value)
|
||||
{
|
||||
if (!EnsureWeakMapData(cx, mapObj))
|
||||
return false;
|
||||
ObjectValueMap* map = mapObj->getMap();
|
||||
if (!map) {
|
||||
auto newMap = cx->make_unique<ObjectValueMap>(cx, mapObj.get());
|
||||
if (!newMap)
|
||||
return false;
|
||||
if (!newMap->init()) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
map = newMap.release();
|
||||
mapObj->setPrivate(map);
|
||||
}
|
||||
|
||||
// Preserve wrapped native keys to prevent wrapper optimization.
|
||||
if (!TryPreserveReflector(cx, key))
|
||||
|
|
@ -236,28 +162,13 @@ SetWeakMapObjectEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetWeakMapSymbolEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj,
|
||||
Handle<JS::Symbol*> key, HandleValue value)
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
WeakMap_set_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
if (!EnsureWeakMapData(cx, mapObj))
|
||||
return false;
|
||||
SymbolValueMap* map = mapObj->getSymbolMap();
|
||||
MOZ_ASSERT(IsWeakMap(args.thisv()));
|
||||
|
||||
MOZ_ASSERT_IF(value.isObject(), value.toObject().compartment() == mapObj->compartment());
|
||||
if (!map->put(key, value)) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
SetWeakMapEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj,
|
||||
HandleValue key, HandleValue value)
|
||||
{
|
||||
if (!CanBeHeldWeakly(key)) {
|
||||
UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, key, nullptr);
|
||||
if (!args.get(0).isObject()) {
|
||||
UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, args.get(0), nullptr);
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT,
|
||||
|
|
@ -265,24 +176,11 @@ SetWeakMapEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (key.isObject()) {
|
||||
RootedObject objectKey(cx, &key.toObject());
|
||||
return SetWeakMapObjectEntryInternal(cx, mapObj, objectKey, value);
|
||||
}
|
||||
|
||||
Rooted<JS::Symbol*> symbolKey(cx, key.toSymbol());
|
||||
return SetWeakMapSymbolEntryInternal(cx, mapObj, symbolKey, value);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
WeakMap_set_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsWeakMap(args.thisv()));
|
||||
|
||||
RootedObject key(cx, &args[0].toObject());
|
||||
Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
|
||||
Rooted<WeakMapObject*> map(cx, &thisObj->as<WeakMapObject>());
|
||||
|
||||
if (!SetWeakMapEntryInternal(cx, map, args.get(0), args.get(1)))
|
||||
if (!SetWeakMapEntryInternal(cx, map, key, args.get(1)))
|
||||
return false;
|
||||
args.rval().set(args.thisv());
|
||||
return true;
|
||||
|
|
@ -295,13 +193,6 @@ js::WeakMap_set(JSContext* cx, unsigned argc, Value* vp)
|
|||
return CallNonGenericMethod<IsWeakMap, WeakMap_set_impl>(cx, args);
|
||||
}
|
||||
|
||||
bool
|
||||
js::SetWeakMapEntryValue(JSContext* cx, HandleObject mapObj, HandleValue key, HandleValue val)
|
||||
{
|
||||
Rooted<WeakMapObject*> rootedMap(cx, &mapObj->as<WeakMapObject>());
|
||||
return SetWeakMapEntryInternal(cx, rootedMap, key, val);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
JS_NondeterministicGetWeakMapKeys(JSContext* cx, HandleObject objArg, MutableHandleObject ret)
|
||||
{
|
||||
|
|
@ -314,11 +205,11 @@ JS_NondeterministicGetWeakMapKeys(JSContext* cx, HandleObject objArg, MutableHan
|
|||
RootedObject arr(cx, NewDenseEmptyArray(cx));
|
||||
if (!arr)
|
||||
return false;
|
||||
WeakMapObject::Data* data = obj->as<WeakMapObject>().getData();
|
||||
if (data) {
|
||||
ObjectValueMap* map = obj->as<WeakMapObject>().getMap();
|
||||
if (map) {
|
||||
// Prevent GC from mutating the weakmap while iterating.
|
||||
AutoSuppressGC suppress(cx);
|
||||
for (ObjectValueMap::Base::Range r = data->objectMap.all(); !r.empty(); r.popFront()) {
|
||||
for (ObjectValueMap::Base::Range r = map->all(); !r.empty(); r.popFront()) {
|
||||
JS::ExposeObjectToActiveJS(r.front().key());
|
||||
RootedObject key(cx, r.front().key());
|
||||
if (!cx->compartment()->wrap(cx, &key))
|
||||
|
|
@ -326,14 +217,6 @@ JS_NondeterministicGetWeakMapKeys(JSContext* cx, HandleObject objArg, MutableHan
|
|||
if (!NewbornArrayPush(cx, arr, ObjectValue(*key)))
|
||||
return false;
|
||||
}
|
||||
for (SymbolValueMap::Base::Range r = data->symbolMap.all(); !r.empty(); r.popFront()) {
|
||||
gc::ExposeGCThingToActiveJS(JS::GCCellPtr(r.front().key().get()));
|
||||
RootedValue key(cx, SymbolValue(r.front().key()));
|
||||
if (!cx->compartment()->wrap(cx, &key))
|
||||
return false;
|
||||
if (!NewbornArrayPush(cx, arr, key))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ret.set(arr);
|
||||
return true;
|
||||
|
|
@ -342,23 +225,21 @@ JS_NondeterministicGetWeakMapKeys(JSContext* cx, HandleObject objArg, MutableHan
|
|||
static void
|
||||
WeakMap_mark(JSTracer* trc, JSObject* obj)
|
||||
{
|
||||
if (WeakMapObject::Data* data = obj->as<WeakMapObject>().getData()) {
|
||||
data->objectMap.trace(trc);
|
||||
data->symbolMap.trace(trc);
|
||||
}
|
||||
if (ObjectValueMap* map = obj->as<WeakMapObject>().getMap())
|
||||
map->trace(trc);
|
||||
}
|
||||
|
||||
static void
|
||||
WeakMap_finalize(FreeOp* fop, JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(fop->maybeOffMainThread());
|
||||
if (WeakMapObject::Data* data = obj->as<WeakMapObject>().getData()) {
|
||||
if (ObjectValueMap* map = obj->as<WeakMapObject>().getMap()) {
|
||||
#ifdef DEBUG
|
||||
data->~Data();
|
||||
memset(static_cast<void*>(data), 0xdc, sizeof(*data));
|
||||
fop->free_(data);
|
||||
map->~ObjectValueMap();
|
||||
memset(static_cast<void*>(map), 0xdc, sizeof(*map));
|
||||
fop->free_(map);
|
||||
#else
|
||||
fop->delete_(data);
|
||||
fop->delete_(map);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -401,8 +282,7 @@ JS::SetWeakMapEntry(JSContext* cx, HandleObject mapObj, HandleObject key,
|
|||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, key, val);
|
||||
Rooted<WeakMapObject*> rootedMap(cx, &mapObj->as<WeakMapObject>());
|
||||
RootedValue keyValue(cx, ObjectValue(*key));
|
||||
return SetWeakMapEntryInternal(cx, rootedMap, keyValue, val);
|
||||
return SetWeakMapEntryInternal(cx, rootedMap, key, val);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -506,3 +386,4 @@ js::InitBareWeakMapCtor(JSContext* cx, HandleObject obj)
|
|||
{
|
||||
return InitWeakMapClass(cx, obj, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,7 @@ class WeakMapObject : public NativeObject
|
|||
public:
|
||||
static const Class class_;
|
||||
|
||||
struct Data;
|
||||
|
||||
Data* getData() { return static_cast<Data*>(getPrivate()); }
|
||||
ObjectValueMap* getMap();
|
||||
SymbolValueMap* getSymbolMap();
|
||||
ObjectValueMap* getMap() { return static_cast<ObjectValueMap*>(getPrivate()); }
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
|
|
|||
|
|
@ -1,208 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "builtin/WeakRefObject.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "gc/Nursery.h"
|
||||
#include "gc/Tracer.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/Interpreter-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
static WeakRefObject::Referent*
|
||||
GetReferent(JSObject* obj)
|
||||
{
|
||||
return obj->as<WeakRefObject>().getData();
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsWeakRef(HandleValue v)
|
||||
{
|
||||
return v.isObject() && v.toObject().is<WeakRefObject>();
|
||||
}
|
||||
|
||||
static bool
|
||||
WeakRef_deref_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsWeakRef(args.thisv()));
|
||||
|
||||
WeakRefObject::Referent* data = GetReferent(&args.thisv().toObject());
|
||||
JSObject* target = data ? data->target.get() : nullptr;
|
||||
if (target)
|
||||
args.rval().setObject(*target);
|
||||
else
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
const JSPropertySpec WeakRefObject::properties[] = {
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
const JSFunctionSpec WeakRefObject::methods[] = {
|
||||
JS_FN("deref", WeakRefObject::deref, 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static JSObject*
|
||||
InitWeakRefClass(JSContext* cx, HandleObject obj, bool defineMembers)
|
||||
{
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
RootedFunction ctor(cx, GlobalObject::createConstructor(cx, WeakRefObject::construct,
|
||||
ClassName(JSProto_WeakRef, cx), 1));
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
|
||||
if (!LinkConstructorAndPrototype(cx, ctor, proto))
|
||||
return nullptr;
|
||||
|
||||
if (defineMembers) {
|
||||
if (!DefinePropertiesAndFunctions(cx, proto, WeakRefObject::properties, WeakRefObject::methods))
|
||||
return nullptr;
|
||||
if (!DefineToStringTag(cx, proto, cx->names().WeakRef))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_WeakRef, ctor, proto))
|
||||
return nullptr;
|
||||
return proto;
|
||||
}
|
||||
|
||||
/* static */ WeakRefObject*
|
||||
WeakRefObject::create(JSContext* cx, HandleObject target, HandleObject proto /* = nullptr */)
|
||||
{
|
||||
Rooted<WeakRefObject*> obj(cx, NewObjectWithClassProto<WeakRefObject>(cx, proto));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
Referent* data = cx->new_<Referent>(target, cx->options().weakRefs());
|
||||
if (!data)
|
||||
return nullptr;
|
||||
|
||||
obj->setPrivate(data);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
WeakRefObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (!ThrowIfNotConstructing(cx, args, "WeakRef"))
|
||||
return false;
|
||||
|
||||
if (!args.get(0).isObject()) {
|
||||
UniqueChars bytes =
|
||||
DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, args.get(0), nullptr);
|
||||
if (!bytes)
|
||||
return false;
|
||||
|
||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT,
|
||||
bytes.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject target(cx, &args[0].toObject());
|
||||
|
||||
RootedObject proto(cx);
|
||||
RootedObject newTarget(cx, &args.newTarget().toObject());
|
||||
if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
|
||||
return false;
|
||||
|
||||
Rooted<WeakRefObject*> obj(cx, WeakRefObject::create(cx, target, proto));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
WeakRefObject::deref(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsWeakRef, WeakRef_deref_impl>(cx, args);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
WeakRefObject::trace(JSTracer* trc, JSObject* obj)
|
||||
{
|
||||
if (Referent* data = GetReferent(obj)) {
|
||||
JSObject* target = data->target.unbarrieredGet();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
// When pref-disabled, keep referent alive via strong trace so deref()
|
||||
// stays usable as a stub without touching GC internals.
|
||||
if (!data->enabled) {
|
||||
TraceManuallyBarrieredEdge(trc, data->target.unsafeGet(), "WeakRef stub referent");
|
||||
} else if (IsInsideNursery(target)) {
|
||||
// Weak edges must be tenured; trace strongly while referent is in the nursery.
|
||||
TraceManuallyBarrieredEdge(trc, data->target.unsafeGet(), "WeakRef nursery referent");
|
||||
} else {
|
||||
TraceWeakEdge(trc, &data->target, "WeakRef referent");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
WeakRefObject::finalize(FreeOp* fop, JSObject* obj)
|
||||
{
|
||||
if (Referent* data = GetReferent(obj))
|
||||
fop->delete_(data);
|
||||
}
|
||||
|
||||
static const ClassOps WeakRefObjectClassOps = {
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
nullptr, /* getProperty */
|
||||
nullptr, /* setProperty */
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* resolve */
|
||||
nullptr, /* mayResolve */
|
||||
WeakRefObject::finalize,
|
||||
nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
WeakRefObject::trace
|
||||
};
|
||||
|
||||
const Class WeakRefObject::class_ = {
|
||||
"WeakRef",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_WeakRef) |
|
||||
JSCLASS_BACKGROUND_FINALIZE,
|
||||
&WeakRefObjectClassOps
|
||||
};
|
||||
|
||||
/* static */ JSObject*
|
||||
WeakRefObject::initClass(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
return ::InitWeakRefClass(cx, obj, true);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::InitWeakRefClass(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
return WeakRefObject::initClass(cx, obj);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::InitBareWeakRefCtor(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
return ::InitWeakRefClass(cx, obj, false);
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef builtin_WeakRefObject_h
|
||||
#define builtin_WeakRefObject_h
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "vm/NativeObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class WeakRefObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
struct Referent {
|
||||
explicit Referent(JSObject* obj, bool enabled)
|
||||
: target(obj), enabled(enabled) {}
|
||||
WeakRef<JSObject*> target;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static const Class class_;
|
||||
|
||||
static JSObject* initClass(JSContext* cx, HandleObject obj);
|
||||
static WeakRefObject* create(JSContext* cx, HandleObject target, HandleObject proto = nullptr);
|
||||
|
||||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
static void finalize(FreeOp* fop, JSObject* obj);
|
||||
[[nodiscard]] static bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool deref(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
Referent* getData() const {
|
||||
return static_cast<Referent*>(getPrivate());
|
||||
}
|
||||
|
||||
WeakRef<JSObject*>& target() {
|
||||
MOZ_ASSERT(getData());
|
||||
return getData()->target;
|
||||
}
|
||||
|
||||
static const JSPropertySpec properties[];
|
||||
static const JSFunctionSpec methods[];
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
extern JSObject*
|
||||
InitWeakRefClass(JSContext* cx, HandleObject obj);
|
||||
|
||||
extern JSObject*
|
||||
InitBareWeakRefCtor(JSContext* cx, HandleObject obj);
|
||||
|
||||
static inline bool
|
||||
CanBeHeldWeakly(const Value& value)
|
||||
{
|
||||
return value.isObject() || value.isSymbol();
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* builtin_WeakRefObject_h */
|
||||
|
|
@ -32,7 +32,7 @@ function WeakSet_add(value) {
|
|||
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "add", typeof S);
|
||||
|
||||
// Step 5.
|
||||
if (!CanBeHeldWeakly(value))
|
||||
if (!IsObject(value))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, DecompileArg(0, value));
|
||||
|
||||
// Steps 7-8.
|
||||
|
|
@ -55,7 +55,7 @@ function WeakSet_delete(value) {
|
|||
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "delete", typeof S);
|
||||
|
||||
// Step 5.
|
||||
if (!CanBeHeldWeakly(value))
|
||||
if (!IsObject(value))
|
||||
return false;
|
||||
|
||||
// Steps 7-8.
|
||||
|
|
@ -75,7 +75,7 @@ function WeakSet_has(value) {
|
|||
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "has", typeof S);
|
||||
|
||||
// Step 6.
|
||||
if (!CanBeHeldWeakly(value))
|
||||
if (!IsObject(value))
|
||||
return false;
|
||||
|
||||
// Steps 7-8.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include "builtin/MapObject.h"
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "builtin/WeakMapObject.h"
|
||||
#include "builtin/WeakRefObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
|
||||
|
|
@ -109,6 +108,7 @@ WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
if (optimized) {
|
||||
RootedValue keyVal(cx);
|
||||
RootedObject keyObject(cx);
|
||||
RootedValue placeholder(cx, BooleanValue(true));
|
||||
RootedObject map(cx, &obj->getReservedSlot(WEAKSET_MAP_SLOT).toObject());
|
||||
RootedArrayObject array(cx, &iterable.toObject().as<ArrayObject>());
|
||||
|
|
@ -116,7 +116,7 @@ WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
keyVal.set(array->getDenseElement(index));
|
||||
MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE));
|
||||
|
||||
if (!CanBeHeldWeakly(keyVal)) {
|
||||
if (keyVal.isPrimitive()) {
|
||||
UniqueChars bytes =
|
||||
DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, keyVal, nullptr);
|
||||
if (!bytes)
|
||||
|
|
@ -126,7 +126,8 @@ WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!SetWeakMapEntryValue(cx, map, keyVal, placeholder))
|
||||
keyObject = &keyVal.toObject();
|
||||
if (!SetWeakMapEntry(cx, map, keyObject, placeholder))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1470,12 +1470,6 @@ TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_
|
|||
res.isNumber() &&
|
||||
!TypedArrayGetElemStubExists(stub, obj))
|
||||
{
|
||||
if (obj->is<TypedArrayObject>() &&
|
||||
obj->as<TypedArrayObject>().hasResizableOrGrowableBuffer())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!cx->runtime()->jitSupportsFloatingPoint &&
|
||||
(TypedThingRequiresFloatingPoint(obj) || rhs.isDouble()))
|
||||
{
|
||||
|
|
@ -2166,8 +2160,6 @@ ICGetElem_TypedArray::Compiler::generateStubCode(MacroAssembler& masm)
|
|||
Register obj = masm.extractObject(R0, ExtractTemp0);
|
||||
masm.loadPtr(Address(ICStubReg, ICGetElem_TypedArray::offsetOfShape()), scratchReg);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
|
||||
if (layout_ == Layout_TypedArray)
|
||||
GuardResizableOrGrowableTypedArray(masm, obj, scratchReg, &failure);
|
||||
|
||||
// Ensure the index is an integer.
|
||||
if (cx->runtime()->jitSupportsFloatingPoint) {
|
||||
|
|
@ -2639,9 +2631,6 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
|
|||
bool expectOutOfBounds;
|
||||
double idx = index.toNumber();
|
||||
if (obj->is<TypedArrayObject>()) {
|
||||
if (obj->as<TypedArrayObject>().hasResizableOrGrowableBuffer())
|
||||
return true;
|
||||
|
||||
expectOutOfBounds = (idx < 0 || idx >= double(obj->as<TypedArrayObject>().length()));
|
||||
} else {
|
||||
// Typed objects throw on out of bounds accesses. Don't attach
|
||||
|
|
@ -3232,8 +3221,6 @@ ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler& masm)
|
|||
Register obj = masm.extractObject(R0, ExtractTemp0);
|
||||
masm.loadPtr(Address(ICStubReg, ICSetElem_TypedArray::offsetOfShape()), scratchReg);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
|
||||
if (layout_ == Layout_TypedArray)
|
||||
GuardResizableOrGrowableTypedArray(masm, obj, scratchReg, &failure);
|
||||
|
||||
// Ensure the index is an integer.
|
||||
if (cx->runtime()->jitSupportsFloatingPoint) {
|
||||
|
|
|
|||
|
|
@ -8889,17 +8889,9 @@ CodeGenerator::branchIfNotEmptyObjectElements(Register obj, Label* target)
|
|||
Address(obj, NativeObject::offsetOfElements()),
|
||||
ImmPtr(js::emptyObjectElements),
|
||||
&emptyObj);
|
||||
masm.branchPtr(Assembler::Equal,
|
||||
Address(obj, NativeObject::offsetOfElements()),
|
||||
ImmPtr(js::emptyObjectElementsShared),
|
||||
&emptyObj);
|
||||
masm.branchPtr(Assembler::Equal,
|
||||
Address(obj, NativeObject::offsetOfElements()),
|
||||
ImmPtr(js::emptyObjectElementsResizableOrGrowable),
|
||||
&emptyObj);
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(obj, NativeObject::offsetOfElements()),
|
||||
ImmPtr(js::emptyObjectElementsSharedResizableOrGrowable),
|
||||
ImmPtr(js::emptyObjectElementsShared),
|
||||
target);
|
||||
masm.bind(&emptyObj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -537,7 +537,8 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
|||
Label* ifDoesntEmulateUndefined,
|
||||
Register scratch, OutOfLineTestObject* ool);
|
||||
|
||||
// Branch to target unless obj has one of the empty elements pointers.
|
||||
// Branch to target unless obj has an emptyObjectElements or emptyObjectElementsShared
|
||||
// elements pointer.
|
||||
void branchIfNotEmptyObjectElements(Register obj, Label* target);
|
||||
|
||||
void emitStoreElementTyped(const LAllocation* value, MIRType valueType, MIRType elementType,
|
||||
|
|
|
|||
|
|
@ -1245,7 +1245,6 @@ GenerateTypedArrayLength(JSContext* cx, MacroAssembler& masm, IonCache::StubAtta
|
|||
masm.branchPtr(Assembler::AboveOrEqual, tmpReg,
|
||||
ImmPtr(&TypedArrayObject::classes[Scalar::MaxTypedArrayViewType]),
|
||||
failures);
|
||||
GuardResizableOrGrowableTypedArray(masm, object, tmpReg, failures);
|
||||
|
||||
// Load length.
|
||||
masm.loadTypedOrValue(Address(object, TypedArrayObject::lengthOffset()), output);
|
||||
|
|
@ -1645,9 +1644,6 @@ GetPropertyIC::tryAttachTypedArrayLength(JSContext* cx, HandleScript outerScript
|
|||
if (!JSID_IS_ATOM(id, cx->names().length))
|
||||
return true;
|
||||
|
||||
if (obj->as<TypedArrayObject>().hasResizableOrGrowableBuffer())
|
||||
return true;
|
||||
|
||||
if (hasTypedArrayLengthStub(obj))
|
||||
return true;
|
||||
|
||||
|
|
@ -4042,12 +4038,6 @@ GetPropertyIC::canAttachTypedOrUnboxedArrayElement(JSObject* obj, const Value& i
|
|||
if (!obj->is<TypedArrayObject>() && !obj->is<UnboxedArrayObject>())
|
||||
return false;
|
||||
|
||||
if (obj->is<TypedArrayObject>() &&
|
||||
obj->as<TypedArrayObject>().hasResizableOrGrowableBuffer())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(idval.isInt32() || idval.isString());
|
||||
|
||||
// Don't emit a stub if the access is out of bounds. We make to make
|
||||
|
|
@ -4102,9 +4092,6 @@ GenerateGetTypedOrUnboxedArrayElement(JSContext* cx, MacroAssembler& masm,
|
|||
// Decide to what type index the stub should be optimized
|
||||
Register tmpReg = output.scratchReg().gpr();
|
||||
MOZ_ASSERT(tmpReg != InvalidReg);
|
||||
if (array->is<TypedArrayObject>())
|
||||
GuardResizableOrGrowableTypedArray(masm, object, tmpReg, &failures);
|
||||
|
||||
Register indexReg = tmpReg;
|
||||
if (idval.isString()) {
|
||||
MOZ_ASSERT(GetIndexFromString(idval.toString()) != UINT32_MAX);
|
||||
|
|
@ -4588,7 +4575,6 @@ GenerateSetTypedArrayElement(JSContext* cx, MacroAssembler& masm, IonCache::Stub
|
|||
if (!shape)
|
||||
return false;
|
||||
masm.branchTestObjShape(Assembler::NotEqual, object, shape, &failures);
|
||||
GuardResizableOrGrowableTypedArray(masm, object, temp, &failures);
|
||||
|
||||
// Ensure the index is an int32.
|
||||
Register indexReg;
|
||||
|
|
@ -4675,9 +4661,6 @@ SetPropertyIC::tryAttachTypedArrayElement(JSContext* cx, HandleScript outerScrip
|
|||
if (!IsTypedArrayElementSetInlineable(obj, idval, val))
|
||||
return true;
|
||||
|
||||
if (obj->as<TypedArrayObject>().hasResizableOrGrowableBuffer())
|
||||
return true;
|
||||
|
||||
*emitted = true;
|
||||
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
|
|
|
|||
|
|
@ -365,9 +365,13 @@ IonBuilder::inlineNativeGetter(CallInfo& callInfo, JSFunction* target)
|
|||
|
||||
// Try to optimize typed array lengths.
|
||||
if (TypedArrayObject::isOriginalLengthGetter(native)) {
|
||||
// RAB/GSAB views can have dynamic length or temporarily become
|
||||
// out-of-bounds. Let the property IC/VM path handle the getter.
|
||||
return InliningStatus_NotInlined;
|
||||
Scalar::Type type = thisTypes->getTypedArrayType(constraints());
|
||||
if (type == Scalar::MaxTypedArrayViewType)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MInstruction* length = addTypedArrayLength(thisArg);
|
||||
current->push(length);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
// Try to optimize RegExp getters.
|
||||
|
|
@ -2476,10 +2480,21 @@ IsTypedArrayObject(CompilerConstraintList* constraints, MDefinition* def)
|
|||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlinePossiblyWrappedTypedArrayLength(CallInfo& callInfo)
|
||||
{
|
||||
(void) callInfo;
|
||||
MOZ_ASSERT(!callInfo.constructing());
|
||||
MOZ_ASSERT(callInfo.argc() == 1);
|
||||
if (callInfo.getArg(0)->type() != MIRType::Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (getInlineReturnType() != MIRType::Int32)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// RAB/GSAB views require dynamic length semantics.
|
||||
return InliningStatus_NotInlined;
|
||||
if (!IsTypedArrayObject(constraints(), callInfo.getArg(0)))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MInstruction* length = addTypedArrayLength(callInfo.getArg(0));
|
||||
current->push(length);
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
|
|
@ -3236,14 +3251,45 @@ bool
|
|||
IonBuilder::atomicsMeetsPreconditions(CallInfo& callInfo, Scalar::Type* arrayType,
|
||||
bool* requiresTagCheck, AtomicCheckResult checkResult)
|
||||
{
|
||||
(void) callInfo;
|
||||
(void) arrayType;
|
||||
(void) requiresTagCheck;
|
||||
(void) checkResult;
|
||||
if (!JitSupportsAtomics())
|
||||
return false;
|
||||
|
||||
// Atomics bounds checks through addTypedArrayLengthAndData assume stable
|
||||
// SharedArrayBuffer lengths. Avoid this path now that growable SAB exists.
|
||||
return false;
|
||||
if (callInfo.getArg(0)->type() != MIRType::Object)
|
||||
return false;
|
||||
|
||||
if (callInfo.getArg(1)->type() != MIRType::Int32)
|
||||
return false;
|
||||
|
||||
// Ensure that the first argument is a TypedArray that maps shared
|
||||
// memory.
|
||||
//
|
||||
// Then check both that the element type is something we can
|
||||
// optimize and that the return type is suitable for that element
|
||||
// type.
|
||||
|
||||
TemporaryTypeSet* arg0Types = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!arg0Types)
|
||||
return false;
|
||||
|
||||
TemporaryTypeSet::TypedArraySharedness sharedness;
|
||||
*arrayType = arg0Types->getTypedArrayType(constraints(), &sharedness);
|
||||
*requiresTagCheck = sharedness != TemporaryTypeSet::KnownShared;
|
||||
switch (*arrayType) {
|
||||
case Scalar::Int8:
|
||||
case Scalar::Uint8:
|
||||
case Scalar::Int16:
|
||||
case Scalar::Uint16:
|
||||
case Scalar::Int32:
|
||||
return checkResult == DontCheckAtomicResult || getInlineReturnType() == MIRType::Int32;
|
||||
case Scalar::Uint32:
|
||||
// Bug 1077305: it would be attractive to allow inlining even
|
||||
// if the inline return type is Int32, which it will frequently
|
||||
// be.
|
||||
return checkResult == DontCheckAtomicResult || getInlineReturnType() == MIRType::Double;
|
||||
default:
|
||||
// Excludes floating types and Uint8Clamped.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -5505,15 +5505,25 @@ jit::ElementAccessIsTypedArray(CompilerConstraintList* constraints,
|
|||
MDefinition* obj, MDefinition* id,
|
||||
Scalar::Type* arrayType)
|
||||
{
|
||||
(void) constraints;
|
||||
(void) obj;
|
||||
(void) id;
|
||||
(void) arrayType;
|
||||
if (obj->mightBeType(MIRType::String))
|
||||
return false;
|
||||
|
||||
// Resizable ArrayBuffer and growable SharedArrayBuffer views need dynamic
|
||||
// length/out-of-bounds handling. This older MIR path assumes stable
|
||||
// typed-array length/data slots, so keep element accesses on IC/VM paths.
|
||||
return false;
|
||||
if (id->type() != MIRType::Int32 && id->type() != MIRType::Double)
|
||||
return false;
|
||||
|
||||
TemporaryTypeSet* types = obj->resultTypeSet();
|
||||
if (!types)
|
||||
return false;
|
||||
|
||||
*arrayType = types->getTypedArrayType(constraints);
|
||||
|
||||
// FIXME: https://bugzil.la/1536699
|
||||
if (*arrayType == Scalar::MaxTypedArrayViewType ||
|
||||
Scalar::isBigIntType(*arrayType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -3631,17 +3631,6 @@ CheckForTypedObjectWithDetachedStorage(JSContext* cx, MacroAssembler& masm, Labe
|
|||
masm.branch32(Assembler::NotEqual, AbsoluteAddress(address), Imm32(0), failure);
|
||||
}
|
||||
|
||||
void
|
||||
GuardResizableOrGrowableTypedArray(MacroAssembler& masm, Register obj, Register scratch,
|
||||
Label* failure)
|
||||
{
|
||||
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
|
||||
masm.branchTest32(Assembler::NonZero,
|
||||
Address(scratch, ObjectElements::offsetOfFlags()),
|
||||
Imm32(ObjectElements::RESIZABLE_OR_GROWABLE_BUFFER),
|
||||
failure);
|
||||
}
|
||||
|
||||
void
|
||||
LoadTypedThingData(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2307,11 +2307,7 @@ CheckDOMProxyExpandoDoesNotShadow(JSContext* cx, MacroAssembler& masm, Register
|
|||
void
|
||||
CheckForTypedObjectWithDetachedStorage(JSContext* cx, MacroAssembler& masm, Label* failure);
|
||||
|
||||
void
|
||||
GuardResizableOrGrowableTypedArray(MacroAssembler& masm, Register obj, Register scratch,
|
||||
Label* failure);
|
||||
|
||||
[[nodiscard]] bool
|
||||
MOZ_MUST_USE bool
|
||||
DoCallNativeGetter(JSContext* cx, HandleFunction callee, HandleObject obj,
|
||||
MutableHandleValue result);
|
||||
|
||||
|
|
|
|||
|
|
@ -548,8 +548,6 @@ MSG_DEF(JSMSG_TOO_LONG_ARRAY, 0, JSEXN_TYPEERR, "Too long array")
|
|||
|
||||
// Typed array
|
||||
MSG_DEF(JSMSG_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
|
||||
MSG_DEF(JSMSG_ARRAYBUFFER_NOT_RESIZABLE, 0, JSEXN_TYPEERR, "ArrayBuffer is not resizable")
|
||||
MSG_DEF(JSMSG_ARRAYBUFFER_CANNOT_DETACH, 0, JSEXN_TYPEERR, "ArrayBuffer cannot be detached")
|
||||
MSG_DEF(JSMSG_NON_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected ArrayBuffer, but species constructor returned non-ArrayBuffer")
|
||||
MSG_DEF(JSMSG_SAME_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected different ArrayBuffer, but species constructor returned same ArrayBuffer")
|
||||
MSG_DEF(JSMSG_SHORT_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected ArrayBuffer with at least {0} bytes, but species constructor returns ArrayBuffer with {1} bytes")
|
||||
|
|
@ -557,15 +555,12 @@ MSG_DEF(JSMSG_TYPED_ARRAY_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments")
|
|||
MSG_DEF(JSMSG_TYPED_ARRAY_NEGATIVE_ARG,1, JSEXN_RANGEERR, "argument {0} must be >= 0")
|
||||
MSG_DEF(JSMSG_TYPED_ARRAY_DETACHED, 0, JSEXN_TYPEERR, "attempting to access detached ArrayBuffer")
|
||||
MSG_DEF(JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS, 0, JSEXN_RANGEERR, "attempting to construct out-of-bounds TypedArray on ArrayBuffer")
|
||||
MSG_DEF(JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS, 0, JSEXN_TYPEERR, "attempting to access out-of-bounds TypedArray")
|
||||
MSG_DEF(JSMSG_DATA_VIEW_OUT_OF_BOUNDS, 0, JSEXN_TYPEERR, "attempting to access out-of-bounds DataView")
|
||||
MSG_DEF(JSMSG_TYPED_ARRAY_CALL_OR_CONSTRUCT, 1, JSEXN_TYPEERR, "cannot directly {0} builtin %TypedArray%")
|
||||
MSG_DEF(JSMSG_NON_TYPED_ARRAY_RETURNED, 0, JSEXN_TYPEERR, "constructor didn't return TypedArray object")
|
||||
MSG_DEF(JSMSG_SHORT_TYPED_ARRAY_RETURNED, 2, JSEXN_TYPEERR, "expected TypedArray of at least length {0}, but constructor returned TypedArray of length {1}")
|
||||
|
||||
// Shared array buffer
|
||||
MSG_DEF(JSMSG_SHARED_ARRAY_BAD_LENGTH, 0, JSEXN_RANGEERR, "length argument out of range")
|
||||
MSG_DEF(JSMSG_SHARED_ARRAY_NOT_GROWABLE, 0, JSEXN_TYPEERR, "SharedArrayBuffer is not growable")
|
||||
MSG_DEF(JSMSG_NON_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected SharedArrayBuffer, but species constructor returned non-SharedArrayBuffer")
|
||||
MSG_DEF(JSMSG_SAME_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected different SharedArrayBuffer, but species constructor returned same SharedArrayBuffer")
|
||||
MSG_DEF(JSMSG_SHORT_SHARED_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected SharedArrayBuffer with at least {0} bytes, but species constructor returns SharedArrayBuffer with {1} bytes")
|
||||
|
|
|
|||
|
|
@ -951,20 +951,6 @@ LookupStdName(const JSAtomState& names, JSAtom* name, const JSStdName* table)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsStreamExtraName(JSFlatString* name)
|
||||
{
|
||||
return JS_FlatStringEqualsAscii(name, "WritableStream") ||
|
||||
JS_FlatStringEqualsAscii(name, "WritableStreamDefaultWriter") ||
|
||||
JS_FlatStringEqualsAscii(name, "WritableStreamDefaultController") ||
|
||||
JS_FlatStringEqualsAscii(name, "TransformStream") ||
|
||||
JS_FlatStringEqualsAscii(name, "TransformStreamDefaultController") ||
|
||||
JS_FlatStringEqualsAscii(name, "TextEncoderStream") ||
|
||||
JS_FlatStringEqualsAscii(name, "TextDecoderStream") ||
|
||||
JS_FlatStringEqualsAscii(name, "CompressionStream") ||
|
||||
JS_FlatStringEqualsAscii(name, "DecompressionStream");
|
||||
}
|
||||
|
||||
/*
|
||||
* Table of standard classes, indexed by JSProtoKey. For entries where the
|
||||
* JSProtoKey does not correspond to a class with a meaningful constructor, we
|
||||
|
|
@ -1055,27 +1041,11 @@ JS_ResolveStandardClass(JSContext* cx, HandleObject obj, HandleId id, bool* reso
|
|||
if (!GlobalObject::ensureConstructor(cx, global, key))
|
||||
return false;
|
||||
|
||||
if (key == JSProto_ReadableStream) {
|
||||
RootedObject globalObj(cx, global);
|
||||
if (!InitStreamExtras(cx, globalObj))
|
||||
return false;
|
||||
}
|
||||
|
||||
*resolved = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (cx->options().streams() && IsStreamExtraName(idAtom)) {
|
||||
RootedObject globalObj(cx, global);
|
||||
if (!InitStreamExtras(cx, globalObj))
|
||||
return false;
|
||||
|
||||
if (!HasOwnProperty(cx, globalObj, id, resolved))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// There is no such property to resolve. An ordinary resolve hook would
|
||||
// just return true at this point. But the global object is special in one
|
||||
// more way: its prototype chain is lazily initialized. That is,
|
||||
|
|
@ -1105,7 +1075,6 @@ JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj
|
|||
|
||||
return atom == names.undefined ||
|
||||
atom == names.globalThis ||
|
||||
IsStreamExtraName(atom) ||
|
||||
LookupStdName(names, atom, standard_class_names) ||
|
||||
LookupStdName(names, atom, builtin_property_names);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -998,9 +998,7 @@ class JS_PUBLIC_API(ContextOptions) {
|
|||
werror_(false),
|
||||
strictMode_(false),
|
||||
extraWarnings_(false),
|
||||
arrayProtoValues_(true),
|
||||
streams_(true),
|
||||
weakRefs_(false)
|
||||
arrayProtoValues_(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1140,16 +1138,6 @@ class JS_PUBLIC_API(ContextOptions) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool weakRefs() const { return weakRefs_; }
|
||||
ContextOptions& setWeakRefs(bool flag) {
|
||||
weakRefs_ = flag;
|
||||
return *this;
|
||||
}
|
||||
ContextOptions& toggleWeakRefs() {
|
||||
weakRefs_ = !weakRefs_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
bool baseline_ : 1;
|
||||
bool ion_ : 1;
|
||||
|
|
@ -1167,7 +1155,6 @@ class JS_PUBLIC_API(ContextOptions) {
|
|||
bool extraWarnings_ : 1;
|
||||
bool arrayProtoValues_ : 1;
|
||||
bool streams_ : 1;
|
||||
bool weakRefs_ : 1;
|
||||
};
|
||||
|
||||
JS_PUBLIC_API(ContextOptions&)
|
||||
|
|
|
|||
|
|
@ -1221,12 +1221,7 @@ js::array_join(JSContext* cx, unsigned argc, Value* vp)
|
|||
sepstr = cx->names().comma;
|
||||
}
|
||||
|
||||
// Step 6: empty arrays always join to the empty string.
|
||||
// (Separator ToString above still runs for side effects / OOM.)
|
||||
if (length == 0) {
|
||||
args.rval().setString(cx->names().empty);
|
||||
return true;
|
||||
}
|
||||
// Step 6 is implicit in the loops below.
|
||||
|
||||
// An optimized version of a special case of steps 7-11: when length==1 and
|
||||
// the 0th element is a string, ToString() of that element is a no-op and
|
||||
|
|
@ -1386,8 +1381,8 @@ template <JSValueType Type>
|
|||
DenseElementResult
|
||||
ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
|
||||
{
|
||||
/* Empty, singleton, or uninitialized arrays are already reversed. */
|
||||
if (length <= 1 || GetBoxedOrUnboxedInitializedLength<Type>(obj) == 0)
|
||||
/* An empty array or an array with no elements is already reversed. */
|
||||
if (length == 0 || GetBoxedOrUnboxedInitializedLength<Type>(obj) == 0)
|
||||
return DenseElementResult::Success;
|
||||
|
||||
if (Type == JSVAL_TYPE_MAGIC) {
|
||||
|
|
@ -1456,12 +1451,6 @@ js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (!GetLengthProperty(cx, obj, &len))
|
||||
return false;
|
||||
|
||||
// length 0/1: reverse is a no-op; return this immediately.
|
||||
if (len <= 1) {
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ObjectMayHaveExtraIndexedProperties(obj)) {
|
||||
ArrayReverseDenseKernelFunctor functor(cx, obj, len);
|
||||
DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
|
||||
|
|
@ -3227,7 +3216,6 @@ static const JSFunctionSpec array_methods[] = {
|
|||
/* ES2023 proposals */
|
||||
JS_SELF_HOSTED_FN("findLast", "ArrayFindLast", 1,0),
|
||||
JS_SELF_HOSTED_FN("findLastIndex", "ArrayFindLastIndex", 1,0),
|
||||
JS_SELF_HOSTED_FN("toSorted", "ArrayToSorted", 1,0),
|
||||
|
||||
JS_FS_END
|
||||
};
|
||||
|
|
@ -3402,8 +3390,7 @@ array_proto_finish(JSContext* cx, JS::HandleObject ctor, JS::HandleObject proto)
|
|||
!DefineProperty(cx, unscopables, cx->names().flatMap, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().includes, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().keys, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().values, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().toSorted, value))
|
||||
!DefineProperty(cx, unscopables, cx->names().values, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1748,9 +1748,6 @@ JS_IsFloat64Array(JSObject* obj);
|
|||
extern JS_FRIEND_API(bool)
|
||||
JS_GetTypedArraySharedness(JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(uint32_t)
|
||||
JS_GetTypedArrayLength(JSObject* obj);
|
||||
|
||||
/*
|
||||
* Test for specific typed array types (ArrayBufferView subtypes) and return
|
||||
* the unwrapped object if so, else nullptr. Never throws.
|
||||
|
|
@ -1817,7 +1814,8 @@ inline void \
|
|||
Get ## Type ## ArrayLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, type** data) \
|
||||
{ \
|
||||
MOZ_ASSERT(GetObjectClass(obj) == detail::Type ## ArrayClassPtr); \
|
||||
*length = JS_GetTypedArrayLength(obj); \
|
||||
const JS::Value& lenSlot = GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
|
||||
*length = mozilla::AssertedCast<uint32_t>(lenSlot.toInt32()); \
|
||||
*isSharedMemory = JS_GetTypedArraySharedness(obj); \
|
||||
*data = static_cast<type*>(GetObjectPrivate(obj)); \
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ IF_SAB(real,imaginary)(Atomics, InitAtomicsClass, OCLASP(Atomics)) \
|
|||
imaginary(WritableStreamDefaultController,dummy, dummy) \
|
||||
real(ByteLengthQueuingStrategy, InitViaClassSpec, &js::ByteLengthQueuingStrategy::class_) \
|
||||
real(CountQueuingStrategy, InitViaClassSpec, &js::CountQueuingStrategy::class_) \
|
||||
real(WeakRef, InitWeakRefClass, OCLASP(WeakRef)) \
|
||||
|
||||
#define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
|
||||
|
||||
|
|
|
|||
|
|
@ -2329,12 +2329,6 @@ js::str_startsWith(JSContext* cx, unsigned argc, Value* vp)
|
|||
// Step 13
|
||||
uint32_t searchLen = searchStr->length();
|
||||
|
||||
// Empty search string always matches (and is extremely common).
|
||||
if (searchLen == 0) {
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 14
|
||||
if (searchLen + start < searchLen || searchLen + start > textLen) {
|
||||
args.rval().setBoolean(false);
|
||||
|
|
@ -2401,12 +2395,6 @@ js::str_endsWith(JSContext* cx, unsigned argc, Value* vp)
|
|||
// Step 13
|
||||
uint32_t searchLen = searchStr->length();
|
||||
|
||||
// Empty search string always matches.
|
||||
if (searchLen == 0) {
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 15 (reordered)
|
||||
if (searchLen > end) {
|
||||
args.rval().setBoolean(false);
|
||||
|
|
@ -3344,8 +3332,6 @@ static const JSFunctionSpec string_methods[] = {
|
|||
JS_SELF_HOSTED_FN("toLocaleUpperCase", "String_toLocaleUpperCase", 0,0),
|
||||
JS_SELF_HOSTED_FN("localeCompare", "String_localeCompare", 1,0),
|
||||
JS_SELF_HOSTED_FN("repeat", "String_repeat", 1,0),
|
||||
JS_SELF_HOSTED_FN("isWellFormed", "String_isWellFormed", 0,0),
|
||||
JS_SELF_HOSTED_FN("toWellFormed", "String_toWellFormed", 0,0),
|
||||
JS_FN("normalize", str_normalize, 0,0),
|
||||
|
||||
/* Perl-ish methods (search is actually Python-esque). */
|
||||
|
|
|
|||
|
|
@ -16,25 +16,11 @@
|
|||
#include "gc/Marking.h"
|
||||
#include "gc/StoreBuffer.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "vm/Symbol.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class WeakMapBase;
|
||||
|
||||
template <>
|
||||
struct MovableCellHasher<JS::Symbol*>
|
||||
{
|
||||
using Key = JS::Symbol*;
|
||||
using Lookup = JS::Symbol*;
|
||||
|
||||
static bool hasHash(const Lookup& l) { return true; }
|
||||
static bool ensureHash(const Lookup& l) { return true; }
|
||||
static HashNumber hash(const Lookup& l) { return l->hash(); }
|
||||
static bool match(const Key& k, const Lookup& l) { return k == l; }
|
||||
static void rekey(Key& k, const Key& newKey) { k = newKey; }
|
||||
};
|
||||
|
||||
// A subclass template of js::HashMap whose keys and values may be garbage-collected. When
|
||||
// a key is collected, the table entry disappears, dropping its reference to the value.
|
||||
//
|
||||
|
|
@ -310,16 +296,9 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject* getDelegate(JS::Symbol* sym) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void exposeGCThingToActiveJS(const JS::Value& v) const { JS::ExposeValueToActiveJS(v); }
|
||||
void exposeGCThingToActiveJS(JSObject* obj) const { JS::ExposeObjectToActiveJS(obj); }
|
||||
void exposeGCThingToActiveJS(JS::Symbol* sym) const {
|
||||
gc::ExposeGCThingToActiveJS(JS::GCCellPtr(sym));
|
||||
}
|
||||
|
||||
bool keyNeedsMark(JSObject* key) const {
|
||||
JSObject* delegate = getDelegate(key);
|
||||
|
|
@ -334,10 +313,6 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool keyNeedsMark(JS::Symbol* sym) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool findZoneEdges() override {
|
||||
// This is overridden by ObjectValueMap.
|
||||
return true;
|
||||
|
|
@ -403,9 +378,6 @@ WeakMap_set(JSContext* cx, unsigned argc, Value* vp);
|
|||
extern bool
|
||||
WeakMap_delete(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
SetWeakMapEntryValue(JSContext* cx, HandleObject mapObj, HandleValue key, HandleValue val);
|
||||
|
||||
extern JSObject*
|
||||
InitWeakMapClass(JSContext* cx, HandleObject obj);
|
||||
|
||||
|
|
@ -422,16 +394,6 @@ class ObjectValueMap : public WeakMap<HeapPtr<JSObject*>, HeapPtr<Value>,
|
|||
virtual bool findZoneEdges();
|
||||
};
|
||||
|
||||
class SymbolValueMap : public WeakMap<HeapPtr<JS::Symbol*>, HeapPtr<Value>,
|
||||
MovableCellHasher<HeapPtr<JS::Symbol*>>>
|
||||
{
|
||||
public:
|
||||
SymbolValueMap(JSContext* cx, JSObject* obj)
|
||||
: WeakMap<HeapPtr<JS::Symbol*>, HeapPtr<Value>,
|
||||
MovableCellHasher<HeapPtr<JS::Symbol*>>>(cx, obj)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Generic weak map for mapping objects to other objects.
|
||||
class ObjectWeakMap
|
||||
|
|
|
|||
|
|
@ -142,7 +142,6 @@ main_deunified_sources = [
|
|||
'builtin/TestingFunctions.cpp',
|
||||
'builtin/TypedObject.cpp',
|
||||
'builtin/WeakMapObject.cpp',
|
||||
'builtin/WeakRefObject.cpp',
|
||||
'builtin/WeakSetObject.cpp',
|
||||
'devtools/sharkctl.cpp',
|
||||
'ds/LifoAlloc.cpp',
|
||||
|
|
|
|||
|
|
@ -3330,15 +3330,6 @@ static const JSClass sandbox_class = {
|
|||
&sandbox_classOps
|
||||
};
|
||||
|
||||
enum GlobalAppSlot {
|
||||
GlobalAppSlotModuleMetadataHook,
|
||||
GlobalAppSlotModuleDynamicImportHook,
|
||||
GlobalAppSlotCount
|
||||
};
|
||||
|
||||
static_assert(GlobalAppSlotCount <= JSCLASS_GLOBAL_APPLICATION_SLOTS,
|
||||
"global application slots overflow");
|
||||
|
||||
static void
|
||||
SetStandardCompartmentOptions(JS::CompartmentOptions& options)
|
||||
{
|
||||
|
|
@ -4167,7 +4158,7 @@ ParseModule(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
const char16_t* chars = stableChars.twoByteRange().begin().get();
|
||||
JS::SourceBufferHolder srcBuf(chars, scriptContents->length(),
|
||||
JS::SourceBufferHolder::NoOwnership);
|
||||
SourceBufferHolder::NoOwnership);
|
||||
|
||||
RootedObject module(cx, frontend::CompileModule(cx, options, srcBuf));
|
||||
if (!module)
|
||||
|
|
@ -4378,7 +4369,7 @@ AbortDynamicModuleImport(JSContext* cx, unsigned argc, Value* vp)
|
|||
RootedString specifier(cx, args[1].toString());
|
||||
Rooted<PromiseObject*> promise(cx, &args[2].toObject().as<PromiseObject>());
|
||||
|
||||
cx->setPendingException(args[3], nullptr);
|
||||
cx->setPendingException(args[3]);
|
||||
return js::FinishDynamicModuleImport(cx, args[0], specifier, promise);
|
||||
}
|
||||
|
||||
|
|
@ -8431,7 +8422,7 @@ main(int argc, char** argv, char** envp)
|
|||
|
||||
JS::SetModuleResolveHook(cx->runtime(), ShellModuleResolveHook);
|
||||
JS::SetModuleDynamicImportHook(cx, ShellModuleDynamicImportHook);
|
||||
JS::SetModuleMetadataHook(cx, CallModuleMetadataHook);
|
||||
JS::SetModuleMetadataHook(cx, ShellModuleMetadataHook);
|
||||
|
||||
result = Shell(cx, &op, envp);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Array.prototype.toSorted test</title>
|
||||
<style>
|
||||
body { font: 14px/1.4 sans-serif; padding: 16px; }
|
||||
.pass { color: #0a0; }
|
||||
.fail { color: #c00; }
|
||||
pre { white-space: pre-wrap; }
|
||||
</style>
|
||||
<pre id="log"></pre>
|
||||
<script>
|
||||
(function() {
|
||||
const log = document.getElementById("log");
|
||||
function write(msg, cls) {
|
||||
const line = document.createElement("div");
|
||||
if (cls) line.className = cls;
|
||||
line.textContent = msg;
|
||||
log.appendChild(line);
|
||||
}
|
||||
|
||||
window.assertEq = function(actual, expected, msg) {
|
||||
if (actual !== expected) {
|
||||
throw new Error((msg ? msg + ": " : "") +
|
||||
"expected " + expected + ", got " + actual);
|
||||
}
|
||||
};
|
||||
|
||||
window.assertThrowsInstanceOf = function(fn, ctor, msg) {
|
||||
let threw = false;
|
||||
try {
|
||||
fn();
|
||||
} catch (e) {
|
||||
if (e instanceof ctor) {
|
||||
threw = true;
|
||||
} else {
|
||||
throw new Error((msg ? msg + ": " : "") +
|
||||
"threw " + e + ", expected " + ctor.name);
|
||||
}
|
||||
}
|
||||
if (!threw) {
|
||||
throw new Error((msg ? msg + ": " : "") + "did not throw");
|
||||
}
|
||||
};
|
||||
|
||||
window.reportCompare = function() {};
|
||||
|
||||
let hadError = false;
|
||||
window.addEventListener("error", function(e) {
|
||||
hadError = true;
|
||||
write("FAIL: " + e.message, "fail");
|
||||
});
|
||||
window.addEventListener("load", function() {
|
||||
write("PASS: toSorted.js loaded", "pass");
|
||||
if (!hadError)
|
||||
write("PASS: all toSorted tests passed", "pass");
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script src="toSorted.js"></script>
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/ */
|
||||
|
||||
assertEq(typeof Array.prototype.toSorted, "function");
|
||||
|
||||
// Non-mutating behavior.
|
||||
let original = [3, 1, 2];
|
||||
let sorted = original.toSorted();
|
||||
assertEq(original !== sorted, true);
|
||||
assertEq(original.join(","), "3,1,2");
|
||||
assertEq(sorted.join(","), "1,2,3");
|
||||
|
||||
// Compare function.
|
||||
let nums = [10, 1, 5];
|
||||
let desc = nums.toSorted((a, b) => b - a);
|
||||
assertEq(desc.join(","), "10,5,1");
|
||||
|
||||
// Stable sort.
|
||||
let stableInput = [
|
||||
{v: 1, id: "a"},
|
||||
{v: 1, id: "b"},
|
||||
{v: 1, id: "c"}
|
||||
];
|
||||
let stableSorted = stableInput.toSorted((x, y) => x.v - y.v);
|
||||
assertEq(stableSorted.map(o => o.id).join(""), "abc");
|
||||
|
||||
// Holes are treated as undefined (properties are created).
|
||||
let sparse = [3, , 1];
|
||||
let sparseSorted = sparse.toSorted();
|
||||
assertEq(sparseSorted.length, 3);
|
||||
assertEq(sparseSorted[0], 1);
|
||||
assertEq(sparseSorted[1], 3);
|
||||
assertEq(2 in sparseSorted, true);
|
||||
assertEq(sparseSorted[2], undefined);
|
||||
|
||||
// Array-like input.
|
||||
let arrayLike = {0: 2, 1: 1, length: 2};
|
||||
let arrayLikeSorted = Array.prototype.toSorted.call(arrayLike);
|
||||
assertEq(Array.isArray(arrayLikeSorted), true);
|
||||
assertEq(arrayLikeSorted.join(","), "1,2");
|
||||
|
||||
// Getter access order (ascending indices).
|
||||
let accessLog = [];
|
||||
let getterArr = {
|
||||
length: 3,
|
||||
get 0() { accessLog.push(0); return 3; },
|
||||
get 1() { accessLog.push(1); return 1; },
|
||||
get 2() { accessLog.push(2); return 2; }
|
||||
};
|
||||
Array.prototype.toSorted.call(getterArr);
|
||||
assertEq(accessLog.join(","), "0,1,2");
|
||||
|
||||
// Comparator errors propagate.
|
||||
assertThrowsInstanceOf(() => [1, 2].toSorted(1), TypeError);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
// |reftest| skip-if(!ArrayBuffer.prototype.transfer)
|
||||
|
||||
var fixed = new ArrayBuffer(4);
|
||||
assertEq(fixed.byteLength, 4);
|
||||
assertEq(fixed.maxByteLength, 4);
|
||||
assertEq(fixed.resizable, false);
|
||||
assertEq(fixed.detached, false);
|
||||
new Uint8Array(fixed).set([1, 2, 3, 4]);
|
||||
fixed.extra = 17;
|
||||
assertEq(Array.from(new Uint8Array(fixed)).join(","), "1,2,3,4");
|
||||
assertThrowsInstanceOf(() => fixed.resize(2), TypeError);
|
||||
assertEq(ArrayBuffer.prototype.transfer.length, 0);
|
||||
assertEq(ArrayBuffer.prototype.transferToFixedLength.length, 0);
|
||||
var resizeArgumentConverted = false;
|
||||
assertThrowsInstanceOf(() => fixed.resize({ valueOf() { resizeArgumentConverted = true; return 1; } }),
|
||||
TypeError);
|
||||
assertEq(resizeArgumentConverted, false);
|
||||
|
||||
var resizable = new ArrayBuffer(4, { maxByteLength: 8 });
|
||||
assertEq(resizable.byteLength, 4);
|
||||
assertEq(resizable.maxByteLength, 8);
|
||||
assertEq(resizable.resizable, true);
|
||||
|
||||
var bytes = new Uint8Array(resizable);
|
||||
bytes[0] = 11;
|
||||
bytes[3] = 44;
|
||||
resizable.resize(6);
|
||||
assertEq(resizable.byteLength, 6);
|
||||
assertEq(new Uint8Array(resizable)[0], 11);
|
||||
assertEq(new Uint8Array(resizable)[3], 44);
|
||||
assertEq(new Uint8Array(resizable)[4], 0);
|
||||
assertThrowsInstanceOf(() => resizable.resize(9), RangeError);
|
||||
|
||||
var source = new ArrayBuffer(4);
|
||||
var sourceBytes = new Uint8Array(source);
|
||||
sourceBytes[0] = 1;
|
||||
sourceBytes[1] = 2;
|
||||
var sourceView = new Uint8Array(source);
|
||||
var moved = source.transfer(6);
|
||||
assertEq(source.detached, true);
|
||||
assertEq(source.byteLength, 0);
|
||||
assertEq(source.maxByteLength, 0);
|
||||
assertEq(sourceView.length, 0);
|
||||
assertEq(moved.byteLength, 6);
|
||||
assertEq(moved.resizable, false);
|
||||
assertEq(moved.maxByteLength, 6);
|
||||
assertEq(new Uint8Array(moved)[0], 1);
|
||||
assertEq(new Uint8Array(moved)[1], 2);
|
||||
assertEq(new Uint8Array(moved)[4], 0);
|
||||
|
||||
var resizableSource = new ArrayBuffer(4, { maxByteLength: 8 });
|
||||
new Uint8Array(resizableSource)[0] = 7;
|
||||
var resizableMoved = resizableSource.transfer();
|
||||
assertEq(resizableSource.detached, true);
|
||||
assertEq(resizableSource.resizable, true);
|
||||
assertEq(resizableMoved.byteLength, 4);
|
||||
assertEq(resizableMoved.maxByteLength, 8);
|
||||
assertEq(resizableMoved.resizable, true);
|
||||
assertEq(new Uint8Array(resizableMoved)[0], 7);
|
||||
|
||||
var fixedMoved = resizableMoved.transferToFixedLength(10);
|
||||
assertEq(resizableMoved.detached, true);
|
||||
assertEq(fixedMoved.byteLength, 10);
|
||||
assertEq(fixedMoved.maxByteLength, 10);
|
||||
assertEq(fixedMoved.resizable, false);
|
||||
assertEq(new Uint8Array(fixedMoved)[0], 7);
|
||||
|
||||
var sliceSource = new ArrayBuffer(8, { maxByteLength: 8 });
|
||||
var sliceSourceBytes = new Uint8Array(sliceSource);
|
||||
for (var i = 0; i < sliceSourceBytes.length; i++)
|
||||
sliceSourceBytes[i] = i + 1;
|
||||
|
||||
sliceSource.constructor = {
|
||||
[Symbol.species]: function(byteLength) {
|
||||
sliceSource.resize(4);
|
||||
return new ArrayBuffer(byteLength);
|
||||
}
|
||||
};
|
||||
|
||||
var sliced = sliceSource.slice(2, 8);
|
||||
var slicedBytes = new Uint8Array(sliced);
|
||||
assertEq(sliced.byteLength, 6);
|
||||
assertEq(slicedBytes[0], 3);
|
||||
assertEq(slicedBytes[1], 4);
|
||||
assertEq(slicedBytes[2], 0);
|
||||
assertEq(slicedBytes[5], 0);
|
||||
|
||||
sliceSource.resize(8);
|
||||
for (var i = 0; i < sliceSourceBytes.length; i++)
|
||||
sliceSourceBytes[i] = i + 1;
|
||||
var zeroCopied = sliceSource.slice(6, 8);
|
||||
assertEq(zeroCopied.byteLength, 2);
|
||||
assertEq(new Uint8Array(zeroCopied)[0], 0);
|
||||
|
||||
assertThrowsInstanceOf(() => new ArrayBuffer(4, { maxByteLength: 3 }), RangeError);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
||||
|
|
@ -1,218 +0,0 @@
|
|||
// |reftest| skip-if(!this.SharedArrayBuffer)
|
||||
|
||||
var rab = new ArrayBuffer(4, { maxByteLength: 16 });
|
||||
var tracking = new Uint8Array(rab);
|
||||
var fixed = new Uint8Array(rab, 1, 2);
|
||||
var bytes = new Uint8Array(rab);
|
||||
|
||||
bytes[1] = 11;
|
||||
bytes[2] = 22;
|
||||
|
||||
assertEq(tracking.length, 4);
|
||||
assertEq(tracking.byteLength, 4);
|
||||
assertEq(tracking.byteOffset, 0);
|
||||
assertEq(fixed.length, 2);
|
||||
assertEq(fixed.byteLength, 2);
|
||||
assertEq(fixed.byteOffset, 1);
|
||||
|
||||
rab.resize(2);
|
||||
assertEq(tracking.length, 2);
|
||||
assertEq(tracking.byteLength, 2);
|
||||
assertEq(fixed.length, 0);
|
||||
assertEq(fixed.byteLength, 0);
|
||||
assertEq(fixed.byteOffset, 0);
|
||||
assertEq(fixed[0], undefined);
|
||||
|
||||
rab.resize(8);
|
||||
assertEq(tracking.length, 8);
|
||||
assertEq(tracking.byteLength, 8);
|
||||
assertEq(fixed.length, 2);
|
||||
assertEq(fixed.byteLength, 2);
|
||||
assertEq(fixed.byteOffset, 1);
|
||||
assertEq(fixed[0], 11);
|
||||
assertEq(fixed[1], 0);
|
||||
tracking[6] = 66;
|
||||
assertEq(new Uint8Array(rab)[6], 66);
|
||||
|
||||
var dv = new DataView(rab, 4);
|
||||
assertEq(dv.byteOffset, 4);
|
||||
assertEq(dv.byteLength, 4);
|
||||
dv.setUint8(0, 44);
|
||||
assertEq(tracking[4], 44);
|
||||
|
||||
rab.resize(3);
|
||||
assertThrowsInstanceOf(() => dv.byteOffset, TypeError);
|
||||
assertThrowsInstanceOf(() => dv.byteLength, TypeError);
|
||||
assertThrowsInstanceOf(() => dv.getUint8(0), TypeError);
|
||||
|
||||
rab.resize(6);
|
||||
assertEq(dv.byteOffset, 4);
|
||||
assertEq(dv.byteLength, 2);
|
||||
assertEq(dv.getUint8(0), 0);
|
||||
|
||||
var fixedDv = new DataView(rab, 4, 2);
|
||||
rab.resize(5);
|
||||
assertThrowsInstanceOf(() => fixedDv.byteOffset, TypeError);
|
||||
assertThrowsInstanceOf(() => fixedDv.byteLength, TypeError);
|
||||
assertThrowsInstanceOf(() => fixedDv.getUint8(0), TypeError);
|
||||
rab.resize(6);
|
||||
assertEq(fixedDv.byteOffset, 4);
|
||||
assertEq(fixedDv.byteLength, 2);
|
||||
|
||||
var methodRab = new ArrayBuffer(4, { maxByteLength: 8 });
|
||||
var methodFixed = new Uint8Array(methodRab, 2, 2);
|
||||
methodRab.resize(2);
|
||||
[
|
||||
() => methodFixed.at(0),
|
||||
() => methodFixed.copyWithin(0, 0),
|
||||
() => methodFixed.entries(),
|
||||
() => methodFixed.every(x => true),
|
||||
() => methodFixed.fill(1),
|
||||
() => methodFixed.filter(x => true),
|
||||
() => methodFixed.find(x => true),
|
||||
() => methodFixed.findIndex(x => true),
|
||||
() => methodFixed.findLast(x => true),
|
||||
() => methodFixed.findLastIndex(x => true),
|
||||
() => methodFixed.forEach(x => x),
|
||||
() => methodFixed.includes(0),
|
||||
() => methodFixed.indexOf(0),
|
||||
() => methodFixed.join(","),
|
||||
() => methodFixed.keys(),
|
||||
() => methodFixed.lastIndexOf(0),
|
||||
() => methodFixed.map(x => x),
|
||||
() => methodFixed.reduce((a, b) => a + b, 0),
|
||||
() => methodFixed.reduceRight((a, b) => a + b, 0),
|
||||
() => methodFixed.reverse(),
|
||||
() => methodFixed.set([1], 0),
|
||||
() => methodFixed.slice(),
|
||||
() => methodFixed.some(x => true),
|
||||
() => methodFixed.sort(),
|
||||
() => methodFixed.subarray(),
|
||||
() => methodFixed.toLocaleString(),
|
||||
() => methodFixed.toReversed(),
|
||||
() => methodFixed.toSorted(),
|
||||
() => methodFixed.toString(),
|
||||
() => methodFixed.values(),
|
||||
() => methodFixed.with(0, 1),
|
||||
() => methodFixed[Symbol.iterator](),
|
||||
].forEach(fn => assertThrowsInstanceOf(fn, TypeError));
|
||||
|
||||
methodRab.resize(4);
|
||||
assertEq(methodFixed.length, 2);
|
||||
|
||||
var sourceRab = new ArrayBuffer(4, { maxByteLength: 8 });
|
||||
var oobSource = new Uint8Array(sourceRab, 2, 2);
|
||||
sourceRab.resize(2);
|
||||
assertThrowsInstanceOf(() => new Uint8Array(oobSource), TypeError);
|
||||
assertThrowsInstanceOf(() => new Uint16Array(oobSource), TypeError);
|
||||
assertThrowsInstanceOf(() => new Uint8Array(4).set(oobSource), TypeError);
|
||||
sourceRab.resize(4);
|
||||
assertEq(new Uint8Array(oobSource).length, 2);
|
||||
|
||||
var ctorRab = new ArrayBuffer(8, { maxByteLength: 8 });
|
||||
var ShrinkingNewTarget = new Proxy(function() {}, {
|
||||
get(target, prop, receiver) {
|
||||
if (prop === "prototype") {
|
||||
ctorRab.resize(2);
|
||||
return DataView.prototype;
|
||||
}
|
||||
return Reflect.get(target, prop, receiver);
|
||||
}
|
||||
});
|
||||
assertThrowsInstanceOf(() => Reflect.construct(DataView, [ctorRab, 4], ShrinkingNewTarget),
|
||||
RangeError);
|
||||
|
||||
var fixedCtorRab = new ArrayBuffer(8, { maxByteLength: 8 });
|
||||
var FixedShrinkingNewTarget = new Proxy(function() {}, {
|
||||
get(target, prop, receiver) {
|
||||
if (prop === "prototype") {
|
||||
fixedCtorRab.resize(5);
|
||||
return DataView.prototype;
|
||||
}
|
||||
return Reflect.get(target, prop, receiver);
|
||||
}
|
||||
});
|
||||
assertThrowsInstanceOf(() => Reflect.construct(DataView, [fixedCtorRab, 4, 2],
|
||||
FixedShrinkingNewTarget),
|
||||
RangeError);
|
||||
|
||||
var gsab = new SharedArrayBuffer(4, { maxByteLength: 16 });
|
||||
var sharedTracking = new Uint8Array(gsab);
|
||||
assertEq(sharedTracking.length, 4);
|
||||
gsab.grow(8);
|
||||
assertEq(sharedTracking.length, 8);
|
||||
sharedTracking[6] = 33;
|
||||
assertEq(new Uint8Array(gsab)[6], 33);
|
||||
|
||||
var sharedDv = new DataView(gsab);
|
||||
assertEq(sharedDv.buffer, gsab);
|
||||
assertEq(sharedDv.byteOffset, 0);
|
||||
assertEq(sharedDv.byteLength, 8);
|
||||
sharedDv.setUint8(7, 99);
|
||||
assertEq(sharedTracking[7], 99);
|
||||
gsab.grow(12);
|
||||
assertEq(sharedDv.byteLength, 12);
|
||||
assertEq(sharedDv.getUint8(7), 99);
|
||||
|
||||
var fixedSharedDv = new DataView(gsab, 4, 2);
|
||||
assertEq(fixedSharedDv.byteOffset, 4);
|
||||
assertEq(fixedSharedDv.byteLength, 2);
|
||||
gsab.grow(16);
|
||||
assertEq(fixedSharedDv.byteOffset, 4);
|
||||
assertEq(fixedSharedDv.byteLength, 2);
|
||||
|
||||
function readLength(view) {
|
||||
return view.length;
|
||||
}
|
||||
|
||||
function readElement(view, index) {
|
||||
return view[index];
|
||||
}
|
||||
|
||||
function writeElement(view, index, value) {
|
||||
view[index] = value;
|
||||
}
|
||||
|
||||
var normal = new Uint8Array(4);
|
||||
normal[0] = 7;
|
||||
for (var i = 0; i < 2000; i++) {
|
||||
assertEq(readLength(normal), 4);
|
||||
assertEq(readElement(normal, 0), 7);
|
||||
writeElement(normal, 1, 8);
|
||||
}
|
||||
|
||||
var icRab = new ArrayBuffer(4, { maxByteLength: 8 });
|
||||
var icTracking = new Uint8Array(icRab);
|
||||
icTracking[0] = 9;
|
||||
assertEq(readLength(icTracking), 4);
|
||||
assertEq(readElement(icTracking, 0), 9);
|
||||
icRab.resize(0);
|
||||
assertEq(readLength(icTracking), 0);
|
||||
assertEq(readElement(icTracking, 0), undefined);
|
||||
writeElement(icTracking, 0, 1);
|
||||
icRab.resize(4);
|
||||
assertEq(readLength(icTracking), 4);
|
||||
assertEq(readElement(icTracking, 0), 0);
|
||||
writeElement(icTracking, 0, 12);
|
||||
assertEq(readElement(icTracking, 0), 12);
|
||||
|
||||
var icFixed = new Uint8Array(icRab, 1, 2);
|
||||
assertEq(readLength(icFixed), 2);
|
||||
icRab.resize(2);
|
||||
assertEq(readLength(icFixed), 0);
|
||||
assertEq(readElement(icFixed, 0), undefined);
|
||||
writeElement(icFixed, 0, 55);
|
||||
icRab.resize(4);
|
||||
assertEq(readLength(icFixed), 2);
|
||||
assertEq(readElement(icFixed, 0), 0);
|
||||
|
||||
var icGsab = new SharedArrayBuffer(4, { maxByteLength: 8 });
|
||||
var icSharedTracking = new Uint8Array(icGsab);
|
||||
assertEq(readLength(icSharedTracking), 4);
|
||||
icGsab.grow(8);
|
||||
assertEq(readLength(icSharedTracking), 8);
|
||||
writeElement(icSharedTracking, 5, 77);
|
||||
assertEq(readElement(icSharedTracking, 5), 77);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
// |reftest| skip-if(!this.SharedArrayBuffer || !this.Atomics || !this.drainJobQueue)
|
||||
|
||||
if (typeof SharedArrayBuffer === "function" && typeof Atomics === "object" &&
|
||||
typeof drainJobQueue === "function") {
|
||||
const sab = new SharedArrayBuffer(4);
|
||||
const i32 = new Int32Array(sab);
|
||||
|
||||
let result = Atomics.waitAsync(i32, 0, 1, 10);
|
||||
assertEq(result.async, false);
|
||||
assertEq(result.value, "not-equal");
|
||||
|
||||
result = Atomics.waitAsync(i32, 0, 0, 0);
|
||||
assertEq(result.async, false);
|
||||
assertEq(result.value, "timed-out");
|
||||
|
||||
result = Atomics.waitAsync(i32, 0, 0);
|
||||
assertEq(result.async, true);
|
||||
let notified;
|
||||
result.value.then(value => {
|
||||
notified = value;
|
||||
});
|
||||
assertEq(Atomics.notify(i32, 0, 1), 1);
|
||||
drainJobQueue();
|
||||
assertEq(notified, "ok");
|
||||
|
||||
result = Atomics.waitAsync(i32, 0, 0, 1);
|
||||
assertEq(result.async, true);
|
||||
let timedOut;
|
||||
result.value.then(value => {
|
||||
timedOut = value;
|
||||
});
|
||||
drainJobQueue();
|
||||
assertEq(timedOut, "timed-out");
|
||||
|
||||
if (typeof BigInt64Array === "function") {
|
||||
const bigSab = new SharedArrayBuffer(16);
|
||||
const i64 = new BigInt64Array(bigSab);
|
||||
const u64 = new BigUint64Array(bigSab);
|
||||
|
||||
assertEq(Atomics.store(i64, 0, -1n), -1n);
|
||||
assertEq(Atomics.load(i64, 0), -1n);
|
||||
assertEq(Atomics.load(u64, 0), 18446744073709551615n);
|
||||
assertEq(Atomics.exchange(i64, 0, 7n), -1n);
|
||||
assertEq(Atomics.compareExchange(i64, 0, 7n, 10n), 7n);
|
||||
assertEq(Atomics.add(i64, 0, 5n), 10n);
|
||||
assertEq(Atomics.load(i64, 0), 15n);
|
||||
assertEq(Atomics.sub(i64, 0, 20n), 15n);
|
||||
assertEq(Atomics.load(i64, 0), -5n);
|
||||
assertEq(Atomics.and(u64, 0, 7n), 18446744073709551611n);
|
||||
assertEq(Atomics.or(u64, 0, 8n), 3n);
|
||||
assertEq(Atomics.xor(u64, 0, 15n), 11n);
|
||||
|
||||
assertThrowsInstanceOf(() => Atomics.waitAsync(u64, 0, 0n), TypeError);
|
||||
|
||||
result = Atomics.waitAsync(i64, 1, 1n, 10);
|
||||
assertEq(result.async, false);
|
||||
assertEq(result.value, "not-equal");
|
||||
|
||||
result = Atomics.waitAsync(i64, 1, 0n, 0);
|
||||
assertEq(result.async, false);
|
||||
assertEq(result.value, "timed-out");
|
||||
|
||||
let offsetView = new BigInt64Array(bigSab, 8);
|
||||
result = Atomics.waitAsync(offsetView, 0, 0n);
|
||||
assertEq(result.async, true);
|
||||
notified = undefined;
|
||||
result.value.then(value => {
|
||||
notified = value;
|
||||
});
|
||||
assertEq(Atomics.notify(i64, 1, 1), 1);
|
||||
drainJobQueue();
|
||||
assertEq(notified, "ok");
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// |reftest| skip-if(!Promise.withResolvers)
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(Promise, "withResolvers");
|
||||
assertEq(desc.enumerable, false);
|
||||
assertEq(desc.configurable, true);
|
||||
assertEq(desc.writable, true);
|
||||
assertEq(Promise.withResolvers.length, 0);
|
||||
assertEq(Promise.withResolvers.name, "withResolvers");
|
||||
|
||||
var capability = Promise.withResolvers();
|
||||
assertEq(capability.promise instanceof Promise, true);
|
||||
assertEq(typeof capability.resolve, "function");
|
||||
assertEq(typeof capability.reject, "function");
|
||||
assertEqArray(Object.keys(capability), ["promise", "resolve", "reject"]);
|
||||
|
||||
capability.resolve(42);
|
||||
capability.promise.then(v => assertEq(v, 42));
|
||||
|
||||
class MyPromise extends Promise {}
|
||||
var subCapability = Promise.withResolvers.call(MyPromise);
|
||||
assertEq(subCapability.promise instanceof MyPromise, true);
|
||||
subCapability.reject("rejected");
|
||||
subCapability.promise.then(
|
||||
() => { throw new Error("expected rejection"); },
|
||||
reason => assertEq(reason, "rejected")
|
||||
);
|
||||
|
||||
assertThrowsInstanceOf(() => Promise.withResolvers.call({}), TypeError);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// |reftest| skip-if(!this.SharedArrayBuffer)
|
||||
|
||||
if (typeof SharedArrayBuffer === "function") {
|
||||
const fixed = new SharedArrayBuffer(4);
|
||||
assertEq(fixed.byteLength, 4);
|
||||
assertEq(fixed.maxByteLength, 4);
|
||||
assertEq(fixed.growable, false);
|
||||
assertThrowsInstanceOf(() => fixed.grow(4), TypeError);
|
||||
|
||||
assertThrowsInstanceOf(() => new SharedArrayBuffer(-1), RangeError);
|
||||
assertThrowsInstanceOf(() => new SharedArrayBuffer(8, {maxByteLength: 4}), RangeError);
|
||||
|
||||
let optionGetterCalled = false;
|
||||
const growable = new SharedArrayBuffer(4, {
|
||||
get maxByteLength() {
|
||||
optionGetterCalled = true;
|
||||
return 16;
|
||||
}
|
||||
});
|
||||
assertEq(optionGetterCalled, true);
|
||||
assertEq(growable.byteLength, 4);
|
||||
assertEq(growable.maxByteLength, 16);
|
||||
assertEq(growable.growable, true);
|
||||
|
||||
const before = new Uint8Array(growable);
|
||||
before[0] = 37;
|
||||
assertEq(growable.grow(12), undefined);
|
||||
assertEq(growable.byteLength, 12);
|
||||
assertEq(growable.maxByteLength, 16);
|
||||
|
||||
const after = new Uint8Array(growable);
|
||||
assertEq(after.length, 12);
|
||||
assertEq(after[0], 37);
|
||||
|
||||
assertThrowsInstanceOf(() => growable.grow(11), RangeError);
|
||||
assertThrowsInstanceOf(() => growable.grow(17), RangeError);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// |reftest| skip-if(!String.prototype.isWellFormed||!String.prototype.toWellFormed)
|
||||
|
||||
assertEq("".isWellFormed(), true);
|
||||
assertEq("abc".isWellFormed(), true);
|
||||
assertEq("\uD83D\uDE00".isWellFormed(), true);
|
||||
assertEq("\uD800".isWellFormed(), false);
|
||||
assertEq("\uDC00".isWellFormed(), false);
|
||||
assertEq("\uD800a".isWellFormed(), false);
|
||||
assertEq("a\uDC00".isWellFormed(), false);
|
||||
assertEq("\uD800\uD800\uDC00".isWellFormed(), false);
|
||||
|
||||
assertEq("abc".toWellFormed(), "abc");
|
||||
assertEq("\uD83D\uDE00".toWellFormed(), "\uD83D\uDE00");
|
||||
assertEq("\uD800".toWellFormed(), "\uFFFD");
|
||||
assertEq("\uDC00".toWellFormed(), "\uFFFD");
|
||||
assertEq("\uD800a\uDC00".toWellFormed(), "\uFFFDa\uFFFD");
|
||||
assertEq("\uD800\uD800\uDC00".toWellFormed(), "\uFFFD\uD800\uDC00");
|
||||
|
||||
assertEq(String.prototype.isWellFormed.call(123), true);
|
||||
assertEq(String.prototype.toWellFormed.call({ toString() { return "\uD800x"; } }), "\uFFFDx");
|
||||
|
||||
assertThrowsInstanceOf(() => String.prototype.isWellFormed.call(null), TypeError);
|
||||
assertThrowsInstanceOf(() => String.prototype.toWellFormed.call(undefined), TypeError);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
var key = Symbol("weak");
|
||||
var map = new WeakMap();
|
||||
assertEq(map.has(key), false);
|
||||
assertEq(map.get(key), undefined);
|
||||
assertEq(map.set(key, 13), map);
|
||||
assertEq(map.has(key), true);
|
||||
assertEq(map.get(key), 13);
|
||||
assertEq(map.delete(key), true);
|
||||
assertEq(map.has(key), false);
|
||||
|
||||
var constructedKey = Symbol("constructed");
|
||||
var constructed = new WeakMap([[constructedKey, 7]]);
|
||||
assertEq(constructed.get(constructedKey), 7);
|
||||
|
||||
var registered = Symbol.for("registered");
|
||||
assertEq(map.has(registered), false);
|
||||
assertEq(map.get(registered), undefined);
|
||||
assertEq(map.delete(registered), false);
|
||||
assertThrowsInstanceOf(() => map.set(registered, 1), TypeError);
|
||||
assertThrowsInstanceOf(() => new WeakMap([[registered, 1]]), TypeError);
|
||||
|
||||
var setKey = Symbol("set");
|
||||
var set = new WeakSet([setKey]);
|
||||
assertEq(set.has(setKey), true);
|
||||
assertEq(set.delete(setKey), true);
|
||||
assertEq(set.has(setKey), false);
|
||||
assertEq(set.add(setKey), set);
|
||||
assertEq(set.has(setKey), true);
|
||||
|
||||
assertEq(set.has(registered), false);
|
||||
assertEq(set.delete(registered), false);
|
||||
assertThrowsInstanceOf(() => set.add(registered), TypeError);
|
||||
assertThrowsInstanceOf(() => new WeakSet([registered]), TypeError);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// |reftest| skip-if(!Object.groupBy||!Map.groupBy)
|
||||
|
||||
var objectGroups = Object.groupBy(["a", "bb", "c"], value => value.length);
|
||||
assertEq(Object.getPrototypeOf(objectGroups), null);
|
||||
assertEqArray(objectGroups["1"], ["a", "c"]);
|
||||
assertEqArray(objectGroups["2"], ["bb"]);
|
||||
|
||||
var symbol = Symbol();
|
||||
var symbolGroups = Object.groupBy([1, 2], value => value === 1 ? symbol : "__proto__");
|
||||
assertEqArray(symbolGroups[symbol], [1]);
|
||||
assertEqArray(symbolGroups.__proto__, [2]);
|
||||
|
||||
var indexes = [];
|
||||
var mapGroups = Map.groupBy(["a", "bb", "c"], (value, index) => {
|
||||
indexes.push(index);
|
||||
return value.length;
|
||||
});
|
||||
assertEq(mapGroups instanceof Map, true);
|
||||
assertEqArray(indexes, [0, 1, 2]);
|
||||
assertEqArray(mapGroups.get(1), ["a", "c"]);
|
||||
assertEqArray(mapGroups.get(2), ["bb"]);
|
||||
|
||||
var key = {};
|
||||
var objectKeyGroups = Map.groupBy([1, 2], value => value === 1 ? key : NaN);
|
||||
assertEqArray(objectKeyGroups.get(key), [1]);
|
||||
assertEqArray(objectKeyGroups.get(NaN), [2]);
|
||||
|
||||
assertThrowsInstanceOf(() => Object.groupBy(null, x => x), TypeError);
|
||||
assertThrowsInstanceOf(() => Map.groupBy(undefined, x => x), TypeError);
|
||||
assertThrowsInstanceOf(() => Object.groupBy([], null), TypeError);
|
||||
assertThrowsInstanceOf(() => Map.groupBy([], null), TypeError);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
# include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include "jsapi.h"
|
||||
#include "jsarray.h"
|
||||
#include "jscntxt.h"
|
||||
|
|
@ -46,7 +45,6 @@
|
|||
#include "vm/Interpreter.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
#include "vm/SharedArrayObject.h"
|
||||
#include "vm/TypedArrayObject.h"
|
||||
#include "vm/WrapperObject.h"
|
||||
#include "wasm/WasmSignalHandlers.h"
|
||||
#include "wasm/WasmTypes.h"
|
||||
|
|
@ -172,18 +170,12 @@ static const JSPropertySpec static_properties[] = {
|
|||
|
||||
|
||||
static const JSFunctionSpec prototype_functions[] = {
|
||||
JS_FN("resize", ArrayBufferObject::fun_resize, 1, 0),
|
||||
JS_SELF_HOSTED_FN("slice", "ArrayBufferSlice", 2, 0),
|
||||
JS_FN("transfer", ArrayBufferObject::fun_transfer, 0, 0),
|
||||
JS_FN("transferToFixedLength", ArrayBufferObject::fun_transferToFixedLength, 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static const JSPropertySpec prototype_properties[] = {
|
||||
JS_PSG("byteLength", ArrayBufferObject::byteLengthGetter, 0),
|
||||
JS_PSG("detached", ArrayBufferObject::detachedGetter, 0),
|
||||
JS_PSG("maxByteLength", ArrayBufferObject::maxByteLengthGetter, 0),
|
||||
JS_PSG("resizable", ArrayBufferObject::resizableGetter, 0),
|
||||
JS_STRING_SYM_PS(toStringTag, "ArrayBuffer", JSPROP_READONLY),
|
||||
JS_PS_END
|
||||
};
|
||||
|
|
@ -260,52 +252,6 @@ ArrayBufferObject::byteLengthGetter(JSContext* cx, unsigned argc, Value* vp)
|
|||
return CallNonGenericMethod<IsArrayBuffer, byteLengthGetterImpl>(cx, args);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
ArrayBufferObject::detachedGetterImpl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsArrayBuffer(args.thisv()));
|
||||
args.rval().setBoolean(args.thisv().toObject().as<ArrayBufferObject>().isDetached());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::detachedGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsArrayBuffer, detachedGetterImpl>(cx, args);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
ArrayBufferObject::maxByteLengthGetterImpl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsArrayBuffer(args.thisv()));
|
||||
ArrayBufferObject& buffer = args.thisv().toObject().as<ArrayBufferObject>();
|
||||
args.rval().setInt32(buffer.isDetached() ? 0 : int32_t(buffer.maxByteLength()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::maxByteLengthGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsArrayBuffer, maxByteLengthGetterImpl>(cx, args);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
ArrayBufferObject::resizableGetterImpl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsArrayBuffer(args.thisv()));
|
||||
args.rval().setBoolean(args.thisv().toObject().as<ArrayBufferObject>().isResizable());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::resizableGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsArrayBuffer, resizableGetterImpl>(cx, args);
|
||||
}
|
||||
|
||||
/*
|
||||
* ArrayBuffer.isView(obj); ES6 (Dec 2013 draft) 24.1.3.1
|
||||
*/
|
||||
|
|
@ -318,39 +264,6 @@ ArrayBufferObject::fun_isView(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetArrayBufferMaxByteLengthOption(JSContext* cx, HandleValue options,
|
||||
uint32_t byteLength, uint32_t* maxByteLength,
|
||||
bool* resizable)
|
||||
{
|
||||
*maxByteLength = byteLength;
|
||||
*resizable = false;
|
||||
|
||||
if (!options.isObject())
|
||||
return true;
|
||||
|
||||
RootedObject opts(cx, &options.toObject());
|
||||
RootedValue maxByteLengthValue(cx);
|
||||
if (!GetProperty(cx, opts, opts, cx->names().maxByteLength, &maxByteLengthValue))
|
||||
return false;
|
||||
|
||||
if (maxByteLengthValue.isUndefined())
|
||||
return true;
|
||||
|
||||
uint64_t max;
|
||||
if (!ToIndex(cx, maxByteLengthValue, &max))
|
||||
return false;
|
||||
|
||||
if (max > INT32_MAX || max < byteLength) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
*maxByteLength = uint32_t(max);
|
||||
*resizable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ES2017 draft 24.1.2.1
|
||||
bool
|
||||
|
|
@ -374,22 +287,12 @@ ArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
// Step 3.
|
||||
uint32_t maxByteLength;
|
||||
bool resizable;
|
||||
if (!GetArrayBufferMaxByteLengthOption(cx, args.get(1), uint32_t(byteLength),
|
||||
&maxByteLength, &resizable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
RootedObject proto(cx);
|
||||
RootedObject newTarget(cx, &args.newTarget().toObject());
|
||||
if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
|
||||
return false;
|
||||
|
||||
JSObject* bufobj = create(cx, uint32_t(byteLength), BufferContents::createPlain(nullptr),
|
||||
OwnsData, proto, GenericObject, maxByteLength, resizable);
|
||||
JSObject* bufobj = create(cx, uint32_t(byteLength), proto);
|
||||
if (!bufobj)
|
||||
return false;
|
||||
args.rval().setObject(*bufobj);
|
||||
|
|
@ -399,66 +302,13 @@ ArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
static ArrayBufferObject::BufferContents
|
||||
AllocateArrayBufferContents(JSContext* cx, uint32_t nbytes)
|
||||
{
|
||||
uint8_t* p = cx->runtime()->pod_callocCanGC<uint8_t>(nbytes ? nbytes : 1);
|
||||
uint8_t* p = cx->runtime()->pod_callocCanGC<uint8_t>(nbytes);
|
||||
if (!p)
|
||||
ReportOutOfMemory(cx);
|
||||
|
||||
return ArrayBufferObject::BufferContents::create<ArrayBufferObject::PLAIN>(p);
|
||||
}
|
||||
|
||||
static bool
|
||||
ReportArrayBufferNotResizable(JSContext* cx)
|
||||
{
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARRAYBUFFER_NOT_RESIZABLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
ReportArrayBufferCannotDetach(JSContext* cx)
|
||||
{
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARRAYBUFFER_CANNOT_DETACH);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
ReportArrayBufferLengthOutOfRange(JSContext* cx)
|
||||
{
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
ArrayBufferViewFits(ArrayBufferViewObject* view, uint32_t newByteLength)
|
||||
{
|
||||
if (view->is<DataViewObject>()) {
|
||||
DataViewObject& dataView = view->as<DataViewObject>();
|
||||
uint32_t byteOffset = dataView.byteOffsetMaybeOutOfBounds();
|
||||
if (byteOffset > newByteLength)
|
||||
return false;
|
||||
uint32_t byteLength = dataView.isLengthTracking()
|
||||
? newByteLength - byteOffset
|
||||
: dataView.fixedByteLengthMaybeOutOfBounds();
|
||||
return byteOffset <= newByteLength && byteLength <= newByteLength - byteOffset;
|
||||
}
|
||||
|
||||
if (view->is<TypedArrayObject>()) {
|
||||
TypedArrayObject& typedArray = view->as<TypedArrayObject>();
|
||||
if (typedArray.isSharedMemory())
|
||||
return true;
|
||||
uint32_t byteOffset = typedArray.byteOffsetMaybeOutOfBounds();
|
||||
if (byteOffset > newByteLength)
|
||||
return false;
|
||||
uint32_t byteLength = typedArray.isLengthTracking()
|
||||
? newByteLength - byteOffset
|
||||
: typedArray.fixedLengthMaybeOutOfBounds() *
|
||||
typedArray.bytesPerElement();
|
||||
return byteOffset <= newByteLength && byteLength <= newByteLength - byteOffset;
|
||||
}
|
||||
|
||||
// Outline typed objects don't have a recoverable fixed byte range here.
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
NoteViewBufferWasDetached(ArrayBufferViewObject* view,
|
||||
ArrayBufferObject::BufferContents newContents,
|
||||
|
|
@ -541,8 +391,7 @@ ArrayBufferObject::setNewData(FreeOp* fop, BufferContents newContents, OwnsState
|
|||
|
||||
void
|
||||
ArrayBufferObject::changeViewContents(JSContext* cx, ArrayBufferViewObject* view,
|
||||
uint8_t* oldDataPointer, BufferContents newContents,
|
||||
uint32_t newByteLength)
|
||||
uint8_t* oldDataPointer, BufferContents newContents)
|
||||
{
|
||||
MOZ_ASSERT(!view->isSharedMemory());
|
||||
|
||||
|
|
@ -553,18 +402,7 @@ ArrayBufferObject::changeViewContents(JSContext* cx, ArrayBufferViewObject* view
|
|||
uint8_t* viewDataPointer = view->dataPointerUnshared(nogc);
|
||||
if (viewDataPointer) {
|
||||
MOZ_ASSERT(newContents);
|
||||
uint32_t offset;
|
||||
if (view->is<DataViewObject>()) {
|
||||
offset = view->as<DataViewObject>().byteOffsetMaybeOutOfBounds();
|
||||
} else if (view->is<TypedArrayObject>()) {
|
||||
offset = view->as<TypedArrayObject>().byteOffsetMaybeOutOfBounds();
|
||||
} else {
|
||||
ptrdiff_t oldOffset = viewDataPointer - oldDataPointer;
|
||||
MOZ_ASSERT(oldOffset >= 0);
|
||||
offset = uint32_t(oldOffset);
|
||||
}
|
||||
if (offset > newByteLength)
|
||||
offset = 0;
|
||||
ptrdiff_t offset = viewDataPointer - oldDataPointer;
|
||||
viewDataPointer = static_cast<uint8_t*>(newContents.data()) + offset;
|
||||
view->setDataPointerUnshared(viewDataPointer);
|
||||
}
|
||||
|
|
@ -590,180 +428,10 @@ ArrayBufferObject::changeContents(JSContext* cx, BufferContents newContents,
|
|||
auto& innerViews = cx->compartment()->innerViews.get();
|
||||
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(this)) {
|
||||
for (size_t i = 0; i < views->length(); i++)
|
||||
changeViewContents(cx, (*views)[i], oldDataPointer, newContents, byteLength());
|
||||
changeViewContents(cx, (*views)[i], oldDataPointer, newContents);
|
||||
}
|
||||
if (firstView())
|
||||
changeViewContents(cx, firstView(), oldDataPointer, newContents, byteLength());
|
||||
}
|
||||
|
||||
void
|
||||
ArrayBufferObject::changeContentsForResize(JSContext* cx, BufferContents newContents,
|
||||
OwnsState ownsState, uint32_t newByteLength)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!isWasm());
|
||||
MOZ_ASSERT(!forInlineTypedObject());
|
||||
|
||||
uint8_t* oldDataPointer = dataPointer();
|
||||
setNewData(cx->runtime()->defaultFreeOp(), newContents, ownsState);
|
||||
setByteLength(newByteLength);
|
||||
|
||||
auto& innerViews = cx->compartment()->innerViews.get();
|
||||
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(this)) {
|
||||
for (size_t i = 0; i < views->length(); i++) {
|
||||
ArrayBufferViewObject* view = (*views)[i];
|
||||
if (view->is<DataViewObject>() || view->is<TypedArrayObject>())
|
||||
changeViewContents(cx, view, oldDataPointer, newContents, newByteLength);
|
||||
else if (ArrayBufferViewFits(view, newByteLength))
|
||||
changeViewContents(cx, view, oldDataPointer, newContents, newByteLength);
|
||||
else
|
||||
NoteViewBufferWasDetached(view, newContents, cx);
|
||||
}
|
||||
}
|
||||
|
||||
if (firstView()) {
|
||||
if (firstView()->is<DataViewObject>() || firstView()->is<TypedArrayObject>())
|
||||
changeViewContents(cx, firstView(), oldDataPointer, newContents, newByteLength);
|
||||
else if (ArrayBufferViewFits(firstView(), newByteLength))
|
||||
changeViewContents(cx, firstView(), oldDataPointer, newContents, newByteLength);
|
||||
else
|
||||
NoteViewBufferWasDetached(firstView(), newContents, cx);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ResizeArrayBuffer(JSContext* cx, Handle<ArrayBufferObject*> buffer, uint32_t newByteLength)
|
||||
{
|
||||
if (!buffer->isResizable())
|
||||
return ReportArrayBufferNotResizable(cx);
|
||||
|
||||
if (buffer->isDetached()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newByteLength > buffer->maxByteLength())
|
||||
return ReportArrayBufferLengthOutOfRange(cx);
|
||||
|
||||
if (!buffer->isPlain() || buffer->isPreparedForAsmJS() || buffer->forInlineTypedObject())
|
||||
return ReportArrayBufferCannotDetach(cx);
|
||||
|
||||
if (newByteLength == buffer->byteLength())
|
||||
return true;
|
||||
|
||||
ArrayBufferObject::BufferContents newContents = AllocateArrayBufferContents(cx, newByteLength);
|
||||
if (!newContents)
|
||||
return false;
|
||||
|
||||
uint32_t copyLength = std::min(newByteLength, buffer->byteLength());
|
||||
if (copyLength > 0)
|
||||
memcpy(newContents.data(), buffer->dataPointer(), copyLength);
|
||||
|
||||
buffer->changeContentsForResize(cx, newContents, ArrayBufferObject::OwnsData, newByteLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::fun_resize_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsArrayBuffer(args.thisv()));
|
||||
|
||||
Rooted<ArrayBufferObject*> buffer(cx, &args.thisv().toObject().as<ArrayBufferObject>());
|
||||
if (!buffer->isResizable())
|
||||
return ReportArrayBufferNotResizable(cx);
|
||||
|
||||
uint64_t newByteLength;
|
||||
if (!ToIndex(cx, args.get(0), &newByteLength))
|
||||
return false;
|
||||
if (newByteLength > INT32_MAX)
|
||||
return ReportArrayBufferLengthOutOfRange(cx);
|
||||
|
||||
if (!ResizeArrayBuffer(cx, buffer, uint32_t(newByteLength)))
|
||||
return false;
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::fun_resize(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsArrayBuffer, fun_resize_impl>(cx, args);
|
||||
}
|
||||
|
||||
static bool
|
||||
ArrayBufferTransfer(JSContext* cx, const CallArgs& args, bool preserveResizability)
|
||||
{
|
||||
MOZ_ASSERT(IsArrayBuffer(args.thisv()));
|
||||
Rooted<ArrayBufferObject*> buffer(cx, &args.thisv().toObject().as<ArrayBufferObject>());
|
||||
|
||||
uint32_t newByteLength = buffer->byteLength();
|
||||
if (args.hasDefined(0)) {
|
||||
uint64_t newLength;
|
||||
if (!ToIndex(cx, args.get(0), &newLength))
|
||||
return false;
|
||||
if (newLength > INT32_MAX)
|
||||
return ReportArrayBufferLengthOutOfRange(cx);
|
||||
newByteLength = uint32_t(newLength);
|
||||
}
|
||||
|
||||
if (buffer->isDetached()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer->isWasm() || buffer->isPreparedForAsmJS())
|
||||
return ReportArrayBufferCannotDetach(cx);
|
||||
|
||||
bool newResizable = preserveResizability && buffer->isResizable();
|
||||
uint32_t newMaxByteLength = newResizable ? buffer->maxByteLength() : newByteLength;
|
||||
if (newResizable && newByteLength > newMaxByteLength)
|
||||
return ReportArrayBufferLengthOutOfRange(cx);
|
||||
|
||||
Rooted<ArrayBufferObject*> newBuffer(cx,
|
||||
ArrayBufferObject::create(cx, newByteLength, ArrayBufferObject::BufferContents::createPlain(nullptr),
|
||||
ArrayBufferObject::OwnsData, nullptr, GenericObject,
|
||||
newMaxByteLength, newResizable));
|
||||
if (!newBuffer)
|
||||
return false;
|
||||
|
||||
uint32_t copyLength = std::min(newByteLength, buffer->byteLength());
|
||||
if (copyLength > 0)
|
||||
memcpy(newBuffer->dataPointer(), buffer->dataPointer(), copyLength);
|
||||
|
||||
ArrayBufferObject::BufferContents detachedContents =
|
||||
buffer->hasStealableContents() ? ArrayBufferObject::BufferContents::createPlain(nullptr)
|
||||
: buffer->contents();
|
||||
ArrayBufferObject::detach(cx, buffer, detachedContents);
|
||||
|
||||
args.rval().setObject(*newBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::fun_transfer_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
return ArrayBufferTransfer(cx, args, true);
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::fun_transfer(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsArrayBuffer, fun_transfer_impl>(cx, args);
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::fun_transferToFixedLength_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
return ArrayBufferTransfer(cx, args, false);
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::fun_transferToFixedLength(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsArrayBuffer, fun_transferToFixedLength_impl>(cx, args);
|
||||
changeViewContents(cx, firstView(), oldDataPointer, newContents);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1219,14 +887,6 @@ ArrayBufferObject::byteLength() const
|
|||
return getSlot(BYTE_LENGTH_SLOT).toInt32();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ArrayBufferObject::maxByteLength() const
|
||||
{
|
||||
if (!isResizable())
|
||||
return byteLength();
|
||||
return getSlot(MAX_BYTE_LENGTH_SLOT).toInt32();
|
||||
}
|
||||
|
||||
void
|
||||
ArrayBufferObject::setByteLength(uint32_t length)
|
||||
{
|
||||
|
|
@ -1269,7 +929,7 @@ js::WasmArrayBufferMaxSize(const ArrayBufferObjectMaybeShared* buf)
|
|||
if (buf->is<ArrayBufferObject>())
|
||||
return buf->as<ArrayBufferObject>().wasmMaxSize();
|
||||
|
||||
return Some(buf->as<SharedArrayBufferObject>().maxByteLength());
|
||||
return Some(buf->as<SharedArrayBufferObject>().byteLength());
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
|
|
@ -1375,12 +1035,9 @@ ArrayBufferObject*
|
|||
ArrayBufferObject::create(JSContext* cx, uint32_t nbytes, BufferContents contents,
|
||||
OwnsState ownsState /* = OwnsData */,
|
||||
HandleObject proto /* = nullptr */,
|
||||
NewObjectKind newKind /* = GenericObject */,
|
||||
uint32_t maxByteLength /* = 0 */,
|
||||
bool resizable /* = false */)
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
MOZ_ASSERT_IF(contents.kind() == MAPPED, contents);
|
||||
MOZ_ASSERT_IF(resizable, maxByteLength >= nbytes);
|
||||
|
||||
// 24.1.1.1, step 3 (Inlined 6.2.6.1 CreateByteDataBlock, step 2).
|
||||
// Refuse to allocate too large buffers, currently limited to ~2 GiB.
|
||||
|
|
@ -1389,6 +1046,10 @@ ArrayBufferObject::create(JSContext* cx, uint32_t nbytes, BufferContents content
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// If we need to allocate data, try to use a larger object size class so
|
||||
// that the array buffer's data can be allocated inline with the object.
|
||||
// The extra space will be left unused by the object's fixed slots and
|
||||
// available for the buffer's data, see NewObject().
|
||||
size_t reservedSlots = JSCLASS_RESERVED_SLOTS(&class_);
|
||||
|
||||
size_t nslots = reservedSlots;
|
||||
|
|
@ -1405,10 +1066,18 @@ ArrayBufferObject::create(JSContext* cx, uint32_t nbytes, BufferContents content
|
|||
}
|
||||
} else {
|
||||
MOZ_ASSERT(ownsState == OwnsData);
|
||||
contents = AllocateArrayBufferContents(cx, nbytes);
|
||||
if (!contents)
|
||||
return nullptr;
|
||||
allocated = true;
|
||||
size_t usableSlots = NativeObject::MAX_FIXED_SLOTS - reservedSlots;
|
||||
if (nbytes <= usableSlots * sizeof(Value)) {
|
||||
int newSlots = (nbytes - 1) / sizeof(Value) + 1;
|
||||
MOZ_ASSERT(int(nbytes) <= newSlots * int(sizeof(Value)));
|
||||
nslots = reservedSlots + newSlots;
|
||||
contents = BufferContents::createPlain(nullptr);
|
||||
} else {
|
||||
contents = AllocateArrayBufferContents(cx, nbytes);
|
||||
if (!contents)
|
||||
return nullptr;
|
||||
allocated = true;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!(class_.flags & JSCLASS_HAS_PRIVATE));
|
||||
|
|
@ -1428,11 +1097,10 @@ ArrayBufferObject::create(JSContext* cx, uint32_t nbytes, BufferContents content
|
|||
|
||||
if (!contents) {
|
||||
void* data = obj->inlineDataPointer();
|
||||
memset(data, 0, nbytes);
|
||||
obj->initialize(nbytes, BufferContents::createPlain(data), DoesntOwnData,
|
||||
maxByteLength, resizable);
|
||||
js_memset(data, 0, nbytes);
|
||||
obj->initialize(nbytes, BufferContents::createPlain(data), DoesntOwnData);
|
||||
} else {
|
||||
obj->initialize(nbytes, contents, ownsState, maxByteLength, resizable);
|
||||
obj->initialize(nbytes, contents, ownsState);
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
|
@ -1462,28 +1130,25 @@ ArrayBufferObject::createEmpty(JSContext* cx)
|
|||
bool
|
||||
ArrayBufferObject::createDataViewForThisImpl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsAnyArrayBuffer(args.thisv()));
|
||||
MOZ_ASSERT(IsArrayBuffer(args.thisv()));
|
||||
|
||||
/*
|
||||
* This method is only called for |DataView(alienBuf, ...)| which calls
|
||||
* this as |createDataViewForThis.call(alienBuf, byteOffset, byteLength,
|
||||
* DataView.prototype, lengthTracking)|,
|
||||
* ergo there must be exactly 4 arguments.
|
||||
* DataView.prototype)|,
|
||||
* ergo there must be exactly 3 arguments.
|
||||
*/
|
||||
MOZ_ASSERT(args.length() == 4);
|
||||
MOZ_ASSERT(args.length() == 3);
|
||||
|
||||
uint32_t byteOffset = args[0].toPrivateUint32();
|
||||
uint32_t byteLength = args[1].toPrivateUint32();
|
||||
bool lengthTracking = args[3].toBoolean();
|
||||
Rooted<ArrayBufferObjectMaybeShared*> buffer(cx,
|
||||
&args.thisv().toObject().as<ArrayBufferObjectMaybeShared>());
|
||||
Rooted<ArrayBufferObject*> buffer(cx, &args.thisv().toObject().as<ArrayBufferObject>());
|
||||
|
||||
/*
|
||||
* Pop off the passed-along prototype and delegate to normal DataViewObject
|
||||
* construction.
|
||||
*/
|
||||
JSObject* obj = DataViewObject::create(cx, byteOffset, byteLength, buffer,
|
||||
&args[2].toObject(), lengthTracking);
|
||||
JSObject* obj = DataViewObject::create(cx, byteOffset, byteLength, buffer, &args[2].toObject());
|
||||
if (!obj)
|
||||
return false;
|
||||
args.rval().setObject(*obj);
|
||||
|
|
@ -1494,7 +1159,7 @@ bool
|
|||
ArrayBufferObject::createDataViewForThis(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsAnyArrayBuffer, createDataViewForThisImpl>(cx, args);
|
||||
return CallNonGenericMethod<IsArrayBuffer, createDataViewForThisImpl>(cx, args);
|
||||
}
|
||||
|
||||
/* static */ ArrayBufferObject::BufferContents
|
||||
|
|
@ -1863,8 +1528,6 @@ ArrayBufferViewObject::trace(JSTracer* trc, JSObject* objArg)
|
|||
// The data may or may not be inline with the buffer. The buffer
|
||||
// can only move during a compacting GC, in which case its
|
||||
// objectMoved hook has already updated the buffer's data pointer.
|
||||
if (offset > buf.byteLength())
|
||||
offset = 0;
|
||||
obj->initPrivate(buf.dataPointer() + offset);
|
||||
}
|
||||
}
|
||||
|
|
@ -1915,8 +1578,6 @@ ArrayBufferViewObject::dataPointerUnshared(const JS::AutoRequireNoGC& nogc)
|
|||
bool
|
||||
ArrayBufferViewObject::isSharedMemory()
|
||||
{
|
||||
if (is<DataViewObject>())
|
||||
return as<DataViewObject>().isSharedMemory();
|
||||
if (is<TypedArrayObject>())
|
||||
return as<TypedArrayObject>().isSharedMemory();
|
||||
return false;
|
||||
|
|
@ -1948,7 +1609,7 @@ ArrayBufferViewObject::bufferObject(JSContext* cx, Handle<ArrayBufferViewObject*
|
|||
return thisObject->as<TypedArrayObject>().bufferEither();
|
||||
}
|
||||
MOZ_ASSERT(thisObject->is<DataViewObject>());
|
||||
return &thisObject->as<DataViewObject>().arrayBufferEither();
|
||||
return &thisObject->as<DataViewObject>().arrayBuffer();
|
||||
}
|
||||
|
||||
/* JS Friend API */
|
||||
|
|
@ -2199,7 +1860,7 @@ JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoChe
|
|||
if (!obj)
|
||||
return nullptr;
|
||||
if (obj->is<DataViewObject>()) {
|
||||
*isSharedMemory = obj->as<DataViewObject>().isSharedMemory();
|
||||
*isSharedMemory = false;
|
||||
return obj->as<DataViewObject>().dataPointer();
|
||||
}
|
||||
TypedArrayObject& ta = obj->as<TypedArrayObject>();
|
||||
|
|
@ -2269,7 +1930,7 @@ js::GetArrayBufferViewLengthAndData(JSObject* obj, uint32_t* length, bool* isSha
|
|||
: obj->as<TypedArrayObject>().byteLength();
|
||||
|
||||
if (obj->is<DataViewObject>()) {
|
||||
*isSharedMemory = obj->as<DataViewObject>().isSharedMemory();
|
||||
*isSharedMemory = false;
|
||||
*data = static_cast<uint8_t*>(obj->as<DataViewObject>().dataPointer());
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ ArrayBufferObjectMaybeShared& AsAnyArrayBuffer(HandleValue val);
|
|||
class ArrayBufferObjectMaybeShared : public NativeObject
|
||||
{
|
||||
public:
|
||||
uint32_t byteLength() const {
|
||||
uint32_t byteLength() {
|
||||
return AnyArrayBufferByteLength(this);
|
||||
}
|
||||
|
||||
|
|
@ -128,22 +128,15 @@ typedef MutableHandle<ArrayBufferObjectMaybeShared*> MutableHandleArrayBufferObj
|
|||
class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
||||
{
|
||||
static bool byteLengthGetterImpl(JSContext* cx, const CallArgs& args);
|
||||
static bool maxByteLengthGetterImpl(JSContext* cx, const CallArgs& args);
|
||||
static bool resizableGetterImpl(JSContext* cx, const CallArgs& args);
|
||||
static bool detachedGetterImpl(JSContext* cx, const CallArgs& args);
|
||||
static bool fun_slice_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool fun_resize_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool fun_transfer_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool fun_transferToFixedLength_impl(JSContext* cx, const CallArgs& args);
|
||||
|
||||
public:
|
||||
static const uint8_t DATA_SLOT = 0;
|
||||
static const uint8_t BYTE_LENGTH_SLOT = 1;
|
||||
static const uint8_t FIRST_VIEW_SLOT = 2;
|
||||
static const uint8_t FLAGS_SLOT = 3;
|
||||
static const uint8_t MAX_BYTE_LENGTH_SLOT = 4;
|
||||
|
||||
static const uint8_t RESERVED_SLOTS = 5;
|
||||
static const uint8_t RESERVED_SLOTS = 4;
|
||||
|
||||
static const size_t ARRAY_BUFFER_ALIGNMENT = 8;
|
||||
|
||||
|
|
@ -196,11 +189,7 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
|
||||
// This PLAIN or WASM buffer has been prepared for asm.js and cannot
|
||||
// henceforth be transferred/detached.
|
||||
FOR_ASMJS = 0x40,
|
||||
|
||||
// This buffer was created with [[ArrayBufferMaxByteLength]] and can
|
||||
// be resized up to that maximum.
|
||||
RESIZABLE = 0x80
|
||||
FOR_ASMJS = 0x40
|
||||
};
|
||||
|
||||
static_assert(JS_ARRAYBUFFER_DETACHED_FLAG == DETACHED,
|
||||
|
|
@ -241,14 +230,8 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
static const Class class_;
|
||||
|
||||
static bool byteLengthGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool maxByteLengthGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool resizableGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool detachedGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static bool fun_slice(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool fun_resize(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool fun_transfer(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool fun_transferToFixedLength(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static bool fun_isView(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
|
|
@ -260,9 +243,7 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
BufferContents contents,
|
||||
OwnsState ownsState = OwnsData,
|
||||
HandleObject proto = nullptr,
|
||||
NewObjectKind newKind = GenericObject,
|
||||
uint32_t maxByteLength = 0,
|
||||
bool resizable = false);
|
||||
NewObjectKind newKind = GenericObject);
|
||||
static ArrayBufferObject* create(JSContext* cx, uint32_t nbytes,
|
||||
HandleObject proto = nullptr,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
|
@ -313,8 +294,6 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
|
||||
void setNewData(FreeOp* fop, BufferContents newContents, OwnsState ownsState);
|
||||
void changeContents(JSContext* cx, BufferContents newContents, OwnsState ownsState);
|
||||
void changeContentsForResize(JSContext* cx, BufferContents newContents,
|
||||
OwnsState ownsState, uint32_t newByteLength);
|
||||
|
||||
// Detach this buffer from its original memory. (This necessarily makes
|
||||
// views of this buffer unusable for modifying that original memory.)
|
||||
|
|
@ -323,8 +302,7 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
|
||||
private:
|
||||
void changeViewContents(JSContext* cx, ArrayBufferViewObject* view,
|
||||
uint8_t* oldDataPointer, BufferContents newContents,
|
||||
uint32_t newByteLength);
|
||||
uint8_t* oldDataPointer, BufferContents newContents);
|
||||
void setFirstView(ArrayBufferViewObject* view);
|
||||
|
||||
uint8_t* inlineDataPointer() const;
|
||||
|
|
@ -333,7 +311,6 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
uint8_t* dataPointer() const;
|
||||
SharedMem<uint8_t*> dataPointerShared() const;
|
||||
uint32_t byteLength() const;
|
||||
uint32_t maxByteLength() const;
|
||||
|
||||
BufferContents contents() const {
|
||||
return BufferContents(dataPointer(), bufferKind());
|
||||
|
|
@ -357,7 +334,6 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
bool isWasm() const { return bufferKind() == WASM; }
|
||||
bool isMapped() const { return bufferKind() == MAPPED; }
|
||||
bool isDetached() const { return flags() & DETACHED; }
|
||||
bool isResizable() const { return flags() & RESIZABLE; }
|
||||
bool isPreparedForAsmJS() const { return flags() & FOR_ASMJS; }
|
||||
|
||||
// WebAssembly support:
|
||||
|
|
@ -415,17 +391,12 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
|
||||
void setIsDetached() { setFlags(flags() | DETACHED); }
|
||||
void setIsPreparedForAsmJS() { setFlags(flags() | FOR_ASMJS); }
|
||||
void setIsResizable() { setFlags(flags() | RESIZABLE); }
|
||||
|
||||
void initialize(size_t byteLength, BufferContents contents, OwnsState ownsState,
|
||||
uint32_t maxByteLength = 0, bool resizable = false) {
|
||||
void initialize(size_t byteLength, BufferContents contents, OwnsState ownsState) {
|
||||
setByteLength(byteLength);
|
||||
setFlags(0);
|
||||
setFixedSlot(MAX_BYTE_LENGTH_SLOT, Int32Value(maxByteLength ? maxByteLength : byteLength));
|
||||
setFirstView(nullptr);
|
||||
setDataPointer(contents, ownsState);
|
||||
if (resizable)
|
||||
setIsResizable();
|
||||
}
|
||||
|
||||
// Note: initialize() may be called after initEmpty(); initEmpty() must
|
||||
|
|
@ -433,7 +404,6 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
void initEmpty() {
|
||||
setByteLength(0);
|
||||
setFlags(0);
|
||||
setFixedSlot(MAX_BYTE_LENGTH_SLOT, Int32Value(0));
|
||||
setFirstView(nullptr);
|
||||
setDataPointer(BufferContents::createPlain(nullptr), DoesntOwnData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,7 +248,6 @@
|
|||
macro(lookupSetter, lookupSetter, "__lookupSetter__") \
|
||||
macro(MapConstructorInit, MapConstructorInit, "MapConstructorInit") \
|
||||
macro(MapIterator, MapIterator, "Map Iterator") \
|
||||
macro(maxByteLength, maxByteLength, "maxByteLength") \
|
||||
macro(maximumFractionDigits, maximumFractionDigits, "maximumFractionDigits") \
|
||||
macro(maximumSignificantDigits, maximumSignificantDigits, "maximumSignificantDigits") \
|
||||
macro(message, message, "message") \
|
||||
|
|
@ -430,7 +429,6 @@
|
|||
macro(toJSON, toJSON, "toJSON") \
|
||||
macro(toLocaleString, toLocaleString, "toLocaleString") \
|
||||
macro(toSource, toSource, "toSource") \
|
||||
macro(toSorted, toSorted, "toSorted") \
|
||||
macro(toString, toString, "toString") \
|
||||
macro(toUTCString, toUTCString, "toUTCString") \
|
||||
macro(true, true_, "true") \
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include "builtin/SymbolObject.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "builtin/WeakMapObject.h"
|
||||
#include "builtin/WeakRefObject.h"
|
||||
#include "builtin/WeakSetObject.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
|
|
@ -465,7 +464,6 @@ GlobalObject::initStandardClasses(JSContext* cx, Handle<GlobalObject*> global)
|
|||
if (!ensureConstructor(cx, global, static_cast<JSProtoKey>(k)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -540,7 +538,6 @@ GlobalObject::initSelfHostingBuiltins(JSContext* cx, Handle<GlobalObject*> globa
|
|||
InitBareBuiltinCtor(cx, global, JSProto_Int32Array) &&
|
||||
InitBareSymbolCtor(cx, global) &&
|
||||
InitBareWeakMapCtor(cx, global) &&
|
||||
InitBareWeakRefCtor(cx, global) &&
|
||||
InitStopIterationClass(cx, global) &&
|
||||
DefineFunctions(cx, global, builtins, AsIntrinsic);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,22 +43,6 @@ static const ObjectElements emptyElementsHeaderShared(0, 0, ObjectElements::Shar
|
|||
HeapSlot* const js::emptyObjectElementsShared =
|
||||
reinterpret_cast<HeapSlot*>(uintptr_t(&emptyElementsHeaderShared) + sizeof(ObjectElements));
|
||||
|
||||
static const ObjectElements emptyElementsHeaderResizableOrGrowable(
|
||||
0, 0, ObjectElements::RESIZABLE_OR_GROWABLE_BUFFER);
|
||||
|
||||
/* Objects with no elements share one empty set of elements. */
|
||||
HeapSlot* const js::emptyObjectElementsResizableOrGrowable =
|
||||
reinterpret_cast<HeapSlot*>(uintptr_t(&emptyElementsHeaderResizableOrGrowable) +
|
||||
sizeof(ObjectElements));
|
||||
|
||||
static const ObjectElements emptyElementsHeaderSharedResizableOrGrowable(
|
||||
0, 0, ObjectElements::SHARED_MEMORY | ObjectElements::RESIZABLE_OR_GROWABLE_BUFFER);
|
||||
|
||||
/* Objects with no elements share one empty set of elements. */
|
||||
HeapSlot* const js::emptyObjectElementsSharedResizableOrGrowable =
|
||||
reinterpret_cast<HeapSlot*>(uintptr_t(&emptyElementsHeaderSharedResizableOrGrowable) +
|
||||
sizeof(ObjectElements));
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
|
|
@ -77,12 +61,10 @@ ObjectElements::ConvertElementsToDoubles(JSContext* cx, uintptr_t elementsPtr)
|
|||
* This function is infallible, but has a fallible interface so that it can
|
||||
* be called directly from Ion code. Only arrays can have their dense
|
||||
* elements converted to doubles, and arrays never have empty elements.
|
||||
*/
|
||||
*/
|
||||
HeapSlot* elementsHeapPtr = (HeapSlot*) elementsPtr;
|
||||
MOZ_ASSERT(elementsHeapPtr != emptyObjectElements &&
|
||||
elementsHeapPtr != emptyObjectElementsShared &&
|
||||
elementsHeapPtr != emptyObjectElementsResizableOrGrowable &&
|
||||
elementsHeapPtr != emptyObjectElementsSharedResizableOrGrowable);
|
||||
elementsHeapPtr != emptyObjectElementsShared);
|
||||
|
||||
ObjectElements* header = ObjectElements::fromElements(elementsHeapPtr);
|
||||
MOZ_ASSERT(!header->shouldConvertDoubleElements());
|
||||
|
|
|
|||
|
|
@ -185,11 +185,6 @@ class ObjectElements
|
|||
|
||||
// These elements are set to integrity level "frozen".
|
||||
FROZEN = 0x10,
|
||||
|
||||
// For TypedArrays only: this TypedArray views a resizable
|
||||
// ArrayBuffer or growable SharedArrayBuffer. JIT fast paths with
|
||||
// cached length/data assumptions must fall back for these objects.
|
||||
RESIZABLE_OR_GROWABLE_BUFFER = 0x20,
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -260,10 +255,6 @@ class ObjectElements
|
|||
: flags(SHARED_MEMORY), initializedLength(0), capacity(capacity), length(length)
|
||||
{}
|
||||
|
||||
constexpr ObjectElements(uint32_t capacity, uint32_t length, uint32_t flags)
|
||||
: flags(flags), initializedLength(0), capacity(capacity), length(length)
|
||||
{}
|
||||
|
||||
HeapSlot* elements() {
|
||||
return reinterpret_cast<HeapSlot*>(uintptr_t(this) + sizeof(ObjectElements));
|
||||
}
|
||||
|
|
@ -278,10 +269,6 @@ class ObjectElements
|
|||
return flags & SHARED_MEMORY;
|
||||
}
|
||||
|
||||
bool hasResizableOrGrowableBuffer() const {
|
||||
return flags & RESIZABLE_OR_GROWABLE_BUFFER;
|
||||
}
|
||||
|
||||
GCPtrNativeObject& ownerObject() const {
|
||||
MOZ_ASSERT(isCopyOnWrite());
|
||||
return *(GCPtrNativeObject*)(&elements()[initializedLength]);
|
||||
|
|
@ -339,8 +326,6 @@ static_assert(ObjectElements::VALUES_PER_HEADER * sizeof(HeapSlot) == sizeof(Obj
|
|||
*/
|
||||
extern HeapSlot* const emptyObjectElements;
|
||||
extern HeapSlot* const emptyObjectElementsShared;
|
||||
extern HeapSlot* const emptyObjectElementsResizableOrGrowable;
|
||||
extern HeapSlot* const emptyObjectElementsSharedResizableOrGrowable;
|
||||
|
||||
struct Class;
|
||||
class GCMarker;
|
||||
|
|
@ -495,12 +480,6 @@ class NativeObject : public ShapedObject
|
|||
elements_ = emptyObjectElementsShared;
|
||||
}
|
||||
|
||||
void setHasResizableOrGrowableBuffer() {
|
||||
MOZ_ASSERT(elements_ == emptyObjectElements || elements_ == emptyObjectElementsShared);
|
||||
elements_ = isSharedMemory() ? emptyObjectElementsSharedResizableOrGrowable
|
||||
: emptyObjectElementsResizableOrGrowable;
|
||||
}
|
||||
|
||||
bool isInWholeCellBuffer() const {
|
||||
const gc::TenuredCell* cell = &asTenured();
|
||||
gc::ArenaCellSet* cells = cell->arena()->bufferedCells;
|
||||
|
|
@ -1275,10 +1254,7 @@ class NativeObject : public ShapedObject
|
|||
}
|
||||
|
||||
inline bool hasEmptyElements() const {
|
||||
return elements_ == emptyObjectElements ||
|
||||
elements_ == emptyObjectElementsShared ||
|
||||
elements_ == emptyObjectElementsResizableOrGrowable ||
|
||||
elements_ == emptyObjectElementsSharedResizableOrGrowable;
|
||||
return elements_ == emptyObjectElements || elements_ == emptyObjectElementsShared;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "builtin/Stream.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "builtin/WeakRefObject.h"
|
||||
#include "builtin/WeakSetObject.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "gc/Policy.h"
|
||||
|
|
@ -106,14 +105,6 @@ intrinsic_IsObject(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_CanBeHeldWeakly(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(CanBeHeldWeakly(args.get(0)));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_IsArray(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
|
@ -279,20 +270,6 @@ intrinsic_GetBuiltinConstructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_NewMap(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 0);
|
||||
|
||||
Rooted<MapObject*> map(cx, MapObject::create(cx));
|
||||
if (!map)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*map);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
|
@ -1310,36 +1287,6 @@ intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer(JSContext* cx, unsigned arg
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_TypedArrayIsOutOfBounds(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
|
||||
RootedObject obj(cx, &args[0].toObject());
|
||||
MOZ_ASSERT(obj->is<TypedArrayObject>());
|
||||
args.rval().setBoolean(obj->as<TypedArrayObject>().isOutOfBounds());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_PossiblyWrappedTypedArrayIsOutOfBounds(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
MOZ_ASSERT(args[0].isObject());
|
||||
|
||||
JSObject* obj = CheckedUnwrap(&args[0].toObject());
|
||||
if (!obj) {
|
||||
JS_ReportErrorASCII(cx, "Permission denied to access object");
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(obj->is<TypedArrayObject>());
|
||||
args.rval().setBoolean(obj->as<TypedArrayObject>().isOutOfBounds());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_MoveTypedArrayElements(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
|
@ -1462,10 +1409,6 @@ intrinsic_SetFromTypedArrayApproach(JSContext* cx, unsigned argc, Value* vp)
|
|||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
if (unsafeTypedArrayCrossCompartment->isOutOfBounds()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Steps 21, 23.
|
||||
uint32_t unsafeSrcLengthCrossCompartment = unsafeTypedArrayCrossCompartment->length();
|
||||
|
|
@ -2325,10 +2268,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
JS_INLINABLE_FN("std_Math_min", math_min, 2,0, MathMin),
|
||||
JS_INLINABLE_FN("std_Math_abs", math_abs, 1,0, MathAbs),
|
||||
|
||||
JS_FN("std_Map_create", intrinsic_NewMap, 0,0),
|
||||
JS_FN("std_Map_get", MapObject::get, 1,0),
|
||||
JS_FN("std_Map_has", MapObject::has, 1,0),
|
||||
JS_FN("std_Map_set", MapObject::set, 2,0),
|
||||
JS_FN("std_Map_iterator", MapObject::entries, 0,0),
|
||||
|
||||
JS_FN("std_Number_valueOf", num_valueOf, 0,0),
|
||||
|
|
@ -2376,7 +2316,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
// Helper funtions after this point.
|
||||
JS_INLINABLE_FN("ToObject", intrinsic_ToObject, 1,0, IntrinsicToObject),
|
||||
JS_INLINABLE_FN("IsObject", intrinsic_IsObject, 1,0, IntrinsicIsObject),
|
||||
JS_FN("CanBeHeldWeakly", intrinsic_CanBeHeldWeakly, 1,0),
|
||||
JS_INLINABLE_FN("IsArray", intrinsic_IsArray, 1,0, ArrayIsArray),
|
||||
JS_INLINABLE_FN("IsWrappedArrayConstructor", intrinsic_IsWrappedArrayConstructor, 1,0,
|
||||
IntrinsicIsWrappedArrayConstructor),
|
||||
|
|
@ -2536,10 +2475,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
1, 0, IntrinsicPossiblyWrappedTypedArrayLength),
|
||||
JS_FN("PossiblyWrappedTypedArrayHasDetachedBuffer",
|
||||
intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer, 1, 0),
|
||||
JS_FN("TypedArrayIsOutOfBounds",
|
||||
intrinsic_TypedArrayIsOutOfBounds, 1, 0),
|
||||
JS_FN("PossiblyWrappedTypedArrayIsOutOfBounds",
|
||||
intrinsic_PossiblyWrappedTypedArrayIsOutOfBounds, 1, 0),
|
||||
|
||||
JS_FN("MoveTypedArrayElements", intrinsic_MoveTypedArrayElements, 4,0),
|
||||
JS_FN("SetFromTypedArrayApproach",intrinsic_SetFromTypedArrayApproach, 4, 0),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include "mozilla/Atomics.h"
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsprf.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
|
@ -105,18 +104,15 @@ SharedArrayAllocSize(uint32_t length)
|
|||
}
|
||||
|
||||
SharedArrayRawBuffer*
|
||||
SharedArrayRawBuffer::New(JSContext* cx, uint32_t length, uint32_t maxLength, bool growable)
|
||||
SharedArrayRawBuffer::New(JSContext* cx, uint32_t length)
|
||||
{
|
||||
// The value (uint32_t)-1 is used as a signal in various places,
|
||||
// so guard against it on principle.
|
||||
MOZ_ASSERT(length != (uint32_t)-1);
|
||||
MOZ_ASSERT(maxLength != (uint32_t)-1);
|
||||
MOZ_ASSERT(maxLength >= length);
|
||||
|
||||
// Add a page for the header and round to a page boundary.
|
||||
uint32_t allocationLength = growable ? maxLength : length;
|
||||
uint32_t allocSize = SharedArrayAllocSize(allocationLength);
|
||||
if (allocSize <= allocationLength)
|
||||
uint32_t allocSize = SharedArrayAllocSize(length);
|
||||
if (allocSize <= length)
|
||||
return nullptr;
|
||||
|
||||
// Test >= to guard against the case where multiple extant runtimes
|
||||
|
|
@ -131,8 +127,7 @@ SharedArrayRawBuffer::New(JSContext* cx, uint32_t length, uint32_t maxLength, bo
|
|||
}
|
||||
}
|
||||
|
||||
bool preparedForAsmJS =
|
||||
!growable && jit::JitOptions.asmJSAtomicsEnable && IsValidAsmJSHeapLength(length);
|
||||
bool preparedForAsmJS = jit::JitOptions.asmJSAtomicsEnable && IsValidAsmJSHeapLength(length);
|
||||
|
||||
void* p = nullptr;
|
||||
if (preparedForAsmJS) {
|
||||
|
|
@ -166,9 +161,8 @@ SharedArrayRawBuffer::New(JSContext* cx, uint32_t length, uint32_t maxLength, bo
|
|||
|
||||
uint8_t* buffer = reinterpret_cast<uint8_t*>(p) + gc::SystemPageSize();
|
||||
uint8_t* base = buffer - sizeof(SharedArrayRawBuffer);
|
||||
SharedArrayRawBuffer* rawbuf =
|
||||
new (base) SharedArrayRawBuffer(buffer, length, maxLength, growable, preparedForAsmJS);
|
||||
MOZ_ASSERT(rawbuf->allocatedByteLength() == allocationLength); // Deallocation needs this.
|
||||
SharedArrayRawBuffer* rawbuf = new (base) SharedArrayRawBuffer(buffer, length, preparedForAsmJS);
|
||||
MOZ_ASSERT(rawbuf->length == length); // Deallocation needs this
|
||||
return rawbuf;
|
||||
}
|
||||
|
||||
|
|
@ -207,7 +201,7 @@ SharedArrayRawBuffer::dropReference()
|
|||
MOZ_ASSERT(p.asValue() % gc::SystemPageSize() == 0);
|
||||
|
||||
uint8_t* address = p.unwrap(/*safe - only reference*/);
|
||||
uint32_t allocSize = SharedArrayAllocSize(this->allocatedByteLength());
|
||||
uint32_t allocSize = SharedArrayAllocSize(this->length);
|
||||
|
||||
if (this->preparedForAsmJS) {
|
||||
uint32_t mappedSize = SharedArrayMappedSize(allocSize);
|
||||
|
|
@ -227,23 +221,6 @@ SharedArrayRawBuffer::dropReference()
|
|||
numLive--;
|
||||
}
|
||||
|
||||
bool
|
||||
SharedArrayRawBuffer::growTo(uint32_t newLength)
|
||||
{
|
||||
MOZ_ASSERT(growable);
|
||||
MOZ_ASSERT(newLength <= maxLength);
|
||||
|
||||
for (;;) {
|
||||
uint32_t oldLength = length;
|
||||
if (newLength < oldLength)
|
||||
return false;
|
||||
if (newLength == oldLength)
|
||||
return true;
|
||||
if (length.compareExchange(oldLength, newLength))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
SharedArrayBufferObject::byteLengthGetterImpl(JSContext* cx, const CallArgs& args)
|
||||
|
|
@ -260,112 +237,6 @@ SharedArrayBufferObject::byteLengthGetter(JSContext* cx, unsigned argc, Value* v
|
|||
return CallNonGenericMethod<IsSharedArrayBuffer, byteLengthGetterImpl>(cx, args);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
SharedArrayBufferObject::maxByteLengthGetterImpl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsSharedArrayBuffer(args.thisv()));
|
||||
args.rval().setInt32(args.thisv().toObject().as<SharedArrayBufferObject>().maxByteLength());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SharedArrayBufferObject::maxByteLengthGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsSharedArrayBuffer, maxByteLengthGetterImpl>(cx, args);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
SharedArrayBufferObject::growableGetterImpl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsSharedArrayBuffer(args.thisv()));
|
||||
args.rval().setBoolean(args.thisv().toObject().as<SharedArrayBufferObject>().isGrowable());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SharedArrayBufferObject::growableGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsSharedArrayBuffer, growableGetterImpl>(cx, args);
|
||||
}
|
||||
|
||||
static bool
|
||||
ReportSharedArrayBufferNotGrowable(JSContext* cx)
|
||||
{
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SHARED_ARRAY_NOT_GROWABLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
ReportSharedArrayBufferLengthOutOfRange(JSContext* cx)
|
||||
{
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SHARED_ARRAY_BAD_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetSharedArrayBufferMaxByteLengthOption(JSContext* cx, HandleValue options,
|
||||
uint32_t byteLength, uint32_t* maxByteLength,
|
||||
bool* growable)
|
||||
{
|
||||
*maxByteLength = byteLength;
|
||||
*growable = false;
|
||||
|
||||
if (!options.isObject())
|
||||
return true;
|
||||
|
||||
RootedObject opts(cx, &options.toObject());
|
||||
RootedValue maxByteLengthValue(cx);
|
||||
if (!GetProperty(cx, opts, opts, cx->names().maxByteLength, &maxByteLengthValue))
|
||||
return false;
|
||||
|
||||
if (maxByteLengthValue.isUndefined())
|
||||
return true;
|
||||
|
||||
uint64_t max;
|
||||
if (!ToIndex(cx, maxByteLengthValue, &max))
|
||||
return false;
|
||||
|
||||
if (max > INT32_MAX || max < byteLength)
|
||||
return ReportSharedArrayBufferLengthOutOfRange(cx);
|
||||
|
||||
*maxByteLength = uint32_t(max);
|
||||
*growable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
SharedArrayBufferObject::fun_grow_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(IsSharedArrayBuffer(args.thisv()));
|
||||
|
||||
Rooted<SharedArrayBufferObject*> buffer(cx,
|
||||
&args.thisv().toObject().as<SharedArrayBufferObject>());
|
||||
if (!buffer->isGrowable())
|
||||
return ReportSharedArrayBufferNotGrowable(cx);
|
||||
|
||||
uint64_t newByteLength;
|
||||
if (!ToIndex(cx, args.get(0), &newByteLength))
|
||||
return false;
|
||||
if (newByteLength > INT32_MAX)
|
||||
return ReportSharedArrayBufferLengthOutOfRange(cx);
|
||||
|
||||
uint32_t newLength = uint32_t(newByteLength);
|
||||
if (newLength > buffer->maxByteLength() || !buffer->growTo(newLength))
|
||||
return ReportSharedArrayBufferLengthOutOfRange(cx);
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SharedArrayBufferObject::fun_grow(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsSharedArrayBuffer, fun_grow_impl>(cx, args);
|
||||
}
|
||||
|
||||
bool
|
||||
SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
|
@ -374,19 +245,11 @@ SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value*
|
|||
if (!ThrowIfNotConstructing(cx, args, "SharedArrayBuffer"))
|
||||
return false;
|
||||
|
||||
uint64_t length64;
|
||||
if (!ToIndex(cx, args.get(0), &length64))
|
||||
return false;
|
||||
// Bugs 1068458, 1161298: Limit length to 2^31-1.
|
||||
if (length64 > INT32_MAX)
|
||||
return ReportSharedArrayBufferLengthOutOfRange(cx);
|
||||
uint32_t length = uint32_t(length64);
|
||||
|
||||
uint32_t maxByteLength;
|
||||
bool growable;
|
||||
if (!GetSharedArrayBufferMaxByteLengthOption(cx, args.get(1), length,
|
||||
&maxByteLength, &growable))
|
||||
{
|
||||
uint32_t length;
|
||||
bool overflow_unused;
|
||||
if (!ToLengthClamped(cx, args.get(0), &length, &overflow_unused) || length > INT32_MAX) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SHARED_ARRAY_BAD_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -395,7 +258,7 @@ SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value*
|
|||
if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
|
||||
return false;
|
||||
|
||||
JSObject* bufobj = New(cx, length, maxByteLength, growable, proto);
|
||||
JSObject* bufobj = New(cx, length, proto);
|
||||
if (!bufobj)
|
||||
return false;
|
||||
args.rval().setObject(*bufobj);
|
||||
|
|
@ -403,10 +266,9 @@ SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value*
|
|||
}
|
||||
|
||||
SharedArrayBufferObject*
|
||||
SharedArrayBufferObject::New(JSContext* cx, uint32_t length, uint32_t maxLength, bool growable,
|
||||
HandleObject proto)
|
||||
SharedArrayBufferObject::New(JSContext* cx, uint32_t length, HandleObject proto)
|
||||
{
|
||||
SharedArrayRawBuffer* buffer = SharedArrayRawBuffer::New(cx, length, maxLength, growable);
|
||||
SharedArrayRawBuffer* buffer = SharedArrayRawBuffer::New(cx, length);
|
||||
if (!buffer)
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -479,7 +341,7 @@ SharedArrayBufferObject::addSizeOfExcludingThis(JSObject* obj, mozilla::MallocSi
|
|||
// just live with the risk.
|
||||
const SharedArrayBufferObject& buf = obj->as<SharedArrayBufferObject>();
|
||||
info->objectsNonHeapElementsShared +=
|
||||
buf.rawBufferObject()->allocatedByteLength() / buf.rawBufferObject()->refcount();
|
||||
buf.byteLength() / buf.rawBufferObject()->refcount();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
|
|
@ -547,15 +409,12 @@ static const JSPropertySpec static_properties[] = {
|
|||
};
|
||||
|
||||
static const JSFunctionSpec prototype_functions[] = {
|
||||
JS_FN("grow", SharedArrayBufferObject::fun_grow, 1, 0),
|
||||
JS_SELF_HOSTED_FN("slice", "SharedArrayBufferSlice", 2, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static const JSPropertySpec prototype_properties[] = {
|
||||
JS_PSG("byteLength", SharedArrayBufferObject::byteLengthGetter, 0),
|
||||
JS_PSG("growable", SharedArrayBufferObject::growableGetter, 0),
|
||||
JS_PSG("maxByteLength", SharedArrayBufferObject::maxByteLengthGetter, 0),
|
||||
JS_STRING_SYM_PS(toStringTag, "SharedArrayBuffer", JSPROP_READONLY),
|
||||
JS_PS_END
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,9 +44,7 @@ class SharedArrayRawBuffer
|
|||
{
|
||||
private:
|
||||
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> refcount_;
|
||||
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> length;
|
||||
uint32_t maxLength;
|
||||
bool growable;
|
||||
uint32_t length;
|
||||
bool preparedForAsmJS;
|
||||
|
||||
// A list of structures representing tasks waiting on some
|
||||
|
|
@ -54,12 +52,9 @@ class SharedArrayRawBuffer
|
|||
FutexWaiter* waiters_;
|
||||
|
||||
protected:
|
||||
SharedArrayRawBuffer(uint8_t* buffer, uint32_t length, uint32_t maxLength, bool growable,
|
||||
bool preparedForAsmJS)
|
||||
SharedArrayRawBuffer(uint8_t* buffer, uint32_t length, bool preparedForAsmJS)
|
||||
: refcount_(1),
|
||||
length(length),
|
||||
maxLength(maxLength),
|
||||
growable(growable),
|
||||
preparedForAsmJS(preparedForAsmJS),
|
||||
waiters_(nullptr)
|
||||
{
|
||||
|
|
@ -67,11 +62,7 @@ class SharedArrayRawBuffer
|
|||
}
|
||||
|
||||
public:
|
||||
static SharedArrayRawBuffer* New(JSContext* cx, uint32_t length, uint32_t maxLength,
|
||||
bool growable);
|
||||
static SharedArrayRawBuffer* New(JSContext* cx, uint32_t length) {
|
||||
return New(cx, length, length, false);
|
||||
}
|
||||
static SharedArrayRawBuffer* New(JSContext* cx, uint32_t length);
|
||||
|
||||
// This may be called from multiple threads. The caller must take
|
||||
// care of mutual exclusion.
|
||||
|
|
@ -94,20 +85,6 @@ class SharedArrayRawBuffer
|
|||
return length;
|
||||
}
|
||||
|
||||
uint32_t maxByteLength() const {
|
||||
return growable ? maxLength : byteLength();
|
||||
}
|
||||
|
||||
uint32_t allocatedByteLength() const {
|
||||
return growable ? maxLength : byteLength();
|
||||
}
|
||||
|
||||
bool isGrowable() const {
|
||||
return growable;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool growTo(uint32_t newLength);
|
||||
|
||||
bool isPreparedForAsmJS() const {
|
||||
return preparedForAsmJS;
|
||||
}
|
||||
|
|
@ -140,9 +117,6 @@ class SharedArrayRawBuffer
|
|||
class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared
|
||||
{
|
||||
static bool byteLengthGetterImpl(JSContext* cx, const CallArgs& args);
|
||||
static bool maxByteLengthGetterImpl(JSContext* cx, const CallArgs& args);
|
||||
static bool growableGetterImpl(JSContext* cx, const CallArgs& args);
|
||||
static bool fun_grow_impl(JSContext* cx, const CallArgs& args);
|
||||
|
||||
public:
|
||||
// RAWBUF_SLOT holds a pointer (as "private" data) to the
|
||||
|
|
@ -154,23 +128,13 @@ class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
static const Class class_;
|
||||
|
||||
static bool byteLengthGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool maxByteLengthGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool growableGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool fun_grow(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static bool class_constructor(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// Create a SharedArrayBufferObject with a new SharedArrayRawBuffer.
|
||||
static SharedArrayBufferObject* New(JSContext* cx,
|
||||
uint32_t length,
|
||||
uint32_t maxLength,
|
||||
bool growable,
|
||||
HandleObject proto = nullptr);
|
||||
static SharedArrayBufferObject* New(JSContext* cx,
|
||||
uint32_t length,
|
||||
HandleObject proto = nullptr) {
|
||||
return New(cx, length, length, false, proto);
|
||||
}
|
||||
|
||||
// Create a SharedArrayBufferObject using an existing SharedArrayRawBuffer.
|
||||
static SharedArrayBufferObject* New(JSContext* cx,
|
||||
|
|
@ -200,15 +164,6 @@ class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
uint32_t byteLength() const {
|
||||
return rawBufferObject()->byteLength();
|
||||
}
|
||||
uint32_t maxByteLength() const {
|
||||
return rawBufferObject()->maxByteLength();
|
||||
}
|
||||
bool isGrowable() const {
|
||||
return rawBufferObject()->isGrowable();
|
||||
}
|
||||
[[nodiscard]] bool growTo(uint32_t newLength) {
|
||||
return rawBufferObject()->growTo(newLength);
|
||||
}
|
||||
bool isPreparedForAsmJS() const {
|
||||
return rawBufferObject()->isPreparedForAsmJS();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
#include "builtin/MapObject.h"
|
||||
#include "js/Date.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "vm/ArrayBufferObject-inl.h"
|
||||
#include "vm/SavedFrame.h"
|
||||
#include "vm/SharedArrayObject.h"
|
||||
#include "vm/TypedArrayObject.h"
|
||||
|
|
|
|||
|
|
@ -1065,40 +1065,16 @@ class TypedArrayMethods
|
|||
if (!ToInt32(cx, args[1], &offset))
|
||||
return false;
|
||||
|
||||
if (offset < 0) {
|
||||
if (offset < 0 || uint32_t(offset) > target->length()) {
|
||||
// the given offset is bogus
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (target->hasDetachedBuffer()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
if (target->isOutOfBounds()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t targetLength = target->length();
|
||||
if (uint32_t(offset) > targetLength) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject arg0(cx, &args[0].toObject());
|
||||
if (arg0->is<TypedArrayObject>()) {
|
||||
Rooted<TypedArrayObject*> source(cx, &arg0->as<TypedArrayObject>());
|
||||
if (source->hasDetachedBuffer()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
if (source->isOutOfBounds()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source->length() > targetLength - offset) {
|
||||
if (arg0->as<TypedArrayObject>().length() > target->length() - offset) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1110,7 +1086,7 @@ class TypedArrayMethods
|
|||
if (!GetLengthProperty(cx, arg0, &len))
|
||||
return false;
|
||||
|
||||
if (len > targetLength - offset) {
|
||||
if (uint32_t(offset) > target->length() || len > target->length() - offset) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1123,32 +1099,13 @@ class TypedArrayMethods
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
setFromTypedArray(JSContext* cx, Handle<SomeTypedArray*> target, HandleObject source,
|
||||
uint32_t offset = 0)
|
||||
{
|
||||
MOZ_ASSERT(source->is<TypedArrayObject>(), "use setFromNonTypedArray");
|
||||
static bool
|
||||
setFromTypedArray(JSContext* cx, Handle<SomeTypedArray*> target, HandleObject source,
|
||||
uint32_t offset = 0)
|
||||
{
|
||||
MOZ_ASSERT(source->is<TypedArrayObject>(), "use setFromNonTypedArray");
|
||||
|
||||
if (target->hasDetachedBuffer()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
if (target->isOutOfBounds()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||
return false;
|
||||
}
|
||||
|
||||
Rooted<TypedArrayObject*> sourceArray(cx, &source->as<TypedArrayObject>());
|
||||
if (sourceArray->hasDetachedBuffer()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
if (sourceArray->isOutOfBounds()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isShared = target->isSharedMemory() || sourceArray->isSharedMemory();
|
||||
bool isShared = target->isSharedMemory() || source->as<TypedArrayObject>().isSharedMemory();
|
||||
|
||||
switch (target->type()) {
|
||||
case Scalar::Int8:
|
||||
|
|
|
|||
|
|
@ -484,9 +484,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
}
|
||||
|
||||
static TypedArrayObject*
|
||||
makeInstance(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> buffer,
|
||||
uint32_t byteOffset, uint32_t len, HandleObject proto,
|
||||
bool lengthTracking = false)
|
||||
makeInstance(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> buffer, uint32_t byteOffset, uint32_t len,
|
||||
HandleObject proto)
|
||||
{
|
||||
MOZ_ASSERT_IF(!buffer, byteOffset == 0);
|
||||
|
||||
|
|
@ -511,19 +510,12 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
return nullptr;
|
||||
|
||||
bool isSharedMemory = buffer && IsSharedArrayBuffer(buffer.get());
|
||||
bool hasResizableOrGrowableBuffer =
|
||||
buffer &&
|
||||
((buffer->is<ArrayBufferObject>() && buffer->as<ArrayBufferObject>().isResizable()) ||
|
||||
(buffer->is<SharedArrayBufferObject>() &&
|
||||
buffer->as<SharedArrayBufferObject>().isGrowable()));
|
||||
|
||||
obj->setFixedSlot(TypedArrayObject::BUFFER_SLOT, ObjectOrNullValue(buffer));
|
||||
// This is invariant. Self-hosting code that sets BUFFER_SLOT
|
||||
// (if it does) must maintain it, should it need to.
|
||||
if (isSharedMemory)
|
||||
obj->setIsSharedMemory();
|
||||
if (hasResizableOrGrowableBuffer)
|
||||
obj->setHasResizableOrGrowableBuffer();
|
||||
|
||||
if (buffer) {
|
||||
obj->initViewData(buffer->dataPointerEither() + byteOffset);
|
||||
|
|
@ -557,9 +549,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
#endif
|
||||
}
|
||||
|
||||
obj->setFixedSlot(TypedArrayObject::LENGTH_SLOT,
|
||||
Int32Value(lengthTracking ? TypedArrayObject::LENGTH_TRACKING
|
||||
: int32_t(len)));
|
||||
obj->setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(len));
|
||||
obj->setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(byteOffset));
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
@ -908,7 +898,6 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
return nullptr; // invalid byteOffset
|
||||
}
|
||||
|
||||
bool lengthTracking = false;
|
||||
uint32_t len;
|
||||
if (lengthInt == -1) {
|
||||
len = (buffer->byteLength() - byteOffset) / sizeof(NativeType);
|
||||
|
|
@ -917,12 +906,6 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
|
||||
return nullptr; // given byte array doesn't map exactly to sizeof(NativeType) * N
|
||||
}
|
||||
if ((buffer->is<ArrayBufferObject>() && buffer->as<ArrayBufferObject>().isResizable()) ||
|
||||
(buffer->is<SharedArrayBufferObject>() &&
|
||||
buffer->as<SharedArrayBufferObject>().isGrowable()))
|
||||
{
|
||||
lengthTracking = true;
|
||||
}
|
||||
} else {
|
||||
len = uint32_t(lengthInt);
|
||||
}
|
||||
|
|
@ -941,7 +924,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
return nullptr; // byteOffset + len is too big for the arraybuffer
|
||||
}
|
||||
|
||||
return makeInstance(cx, buffer, byteOffset, len, proto, lengthTracking);
|
||||
return makeInstance(cx, buffer, byteOffset, len, proto);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -1337,10 +1320,6 @@ TypedArrayObjectTemplate<T>::fromTypedArray(JSContext* cx, HandleObject other, b
|
|||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return nullptr;
|
||||
}
|
||||
if (srcArray->isOutOfBounds()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 9.
|
||||
uint32_t elementLength = srcArray->length();
|
||||
|
|
@ -1880,8 +1859,7 @@ DataViewNewObjectKind(JSContext* cx, uint32_t byteLength, JSObject* proto)
|
|||
|
||||
DataViewObject*
|
||||
DataViewObject::create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
|
||||
Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, JSObject* protoArg,
|
||||
bool lengthTracking)
|
||||
Handle<ArrayBufferObject*> arrayBuffer, JSObject* protoArg)
|
||||
{
|
||||
if (arrayBuffer->isDetached()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
|
|
@ -1890,18 +1868,8 @@ DataViewObject::create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
|
|||
|
||||
MOZ_ASSERT(byteOffset <= INT32_MAX);
|
||||
MOZ_ASSERT(byteLength <= INT32_MAX);
|
||||
|
||||
uint32_t bufferByteLength = arrayBuffer->byteLength();
|
||||
if (byteOffset > bufferByteLength ||
|
||||
(!lengthTracking && byteLength > bufferByteLength - byteOffset))
|
||||
{
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE,
|
||||
"1");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (lengthTracking)
|
||||
byteLength = bufferByteLength - byteOffset;
|
||||
MOZ_ASSERT(byteOffset + byteLength < UINT32_MAX);
|
||||
MOZ_ASSERT(!arrayBuffer || !arrayBuffer->is<SharedArrayBufferObject>());
|
||||
|
||||
RootedObject proto(cx, protoArg);
|
||||
RootedObject obj(cx);
|
||||
|
|
@ -1925,72 +1893,57 @@ DataViewObject::create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
|
|||
}
|
||||
}
|
||||
|
||||
// Caller should have established these preconditions, and no
|
||||
// (non-self-hosted) JS code has had an opportunity to run so nothing can
|
||||
// have invalidated them.
|
||||
MOZ_ASSERT(byteOffset <= arrayBuffer->byteLength());
|
||||
MOZ_ASSERT(byteOffset + byteLength <= arrayBuffer->byteLength());
|
||||
|
||||
DataViewObject& dvobj = obj->as<DataViewObject>();
|
||||
dvobj.setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(byteOffset));
|
||||
dvobj.setFixedSlot(TypedArrayObject::LENGTH_SLOT,
|
||||
Int32Value(lengthTracking ? TypedArrayObject::LENGTH_TRACKING
|
||||
: int32_t(byteLength)));
|
||||
dvobj.setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(byteLength));
|
||||
dvobj.setFixedSlot(TypedArrayObject::BUFFER_SLOT, ObjectValue(*arrayBuffer));
|
||||
auto dataPointer = arrayBuffer->dataPointerEither();
|
||||
dvobj.initPrivate((dataPointer + byteOffset).unwrap(/*safe - stored as private data*/));
|
||||
dvobj.initPrivate(arrayBuffer->dataPointer() + byteOffset);
|
||||
|
||||
// Include a barrier if the data view's data pointer is in the nursery, as
|
||||
// is done for typed arrays.
|
||||
if (arrayBuffer->is<ArrayBufferObject>() &&
|
||||
!IsInsideNursery(obj) &&
|
||||
cx->runtime()->gc.nursery.isInside(dataPointer))
|
||||
{
|
||||
if (!IsInsideNursery(obj) && cx->runtime()->gc.nursery.isInside(arrayBuffer->dataPointer()))
|
||||
cx->runtime()->gc.storeBuffer.putWholeCell(obj);
|
||||
}
|
||||
|
||||
// Verify that the private slot is at the expected place
|
||||
MOZ_ASSERT(dvobj.numFixedSlots() == TypedArrayObject::DATA_SLOT);
|
||||
|
||||
if (arrayBuffer->is<ArrayBufferObject>()) {
|
||||
if (!arrayBuffer->as<ArrayBufferObject>().addView(cx, &dvobj))
|
||||
return nullptr;
|
||||
}
|
||||
if (!arrayBuffer->addView(cx, &dvobj))
|
||||
return nullptr;
|
||||
|
||||
return &dvobj;
|
||||
}
|
||||
|
||||
bool
|
||||
DataViewObject::getAndCheckConstructorArgs(JSContext* cx, JSObject* bufobj, const CallArgs& args,
|
||||
uint32_t* byteOffsetPtr, uint32_t* byteLengthPtr,
|
||||
bool* lengthTrackingPtr)
|
||||
uint32_t* byteOffsetPtr, uint32_t* byteLengthPtr)
|
||||
{
|
||||
if (!IsAnyArrayBuffer(bufobj)) {
|
||||
if (!IsArrayBuffer(bufobj)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
|
||||
"DataView", "ArrayBuffer or SharedArrayBuffer",
|
||||
bufobj->getClass()->name);
|
||||
"DataView", "ArrayBuffer", bufobj->getClass()->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
Rooted<ArrayBufferObjectMaybeShared*> buffer(cx, &bufobj->as<ArrayBufferObjectMaybeShared>());
|
||||
Rooted<ArrayBufferObject*> buffer(cx, &AsArrayBuffer(bufobj));
|
||||
uint32_t byteOffset = 0;
|
||||
uint32_t byteLength = buffer->byteLength();
|
||||
bool isResizableOrGrowable =
|
||||
(buffer->is<ArrayBufferObject>() && buffer->as<ArrayBufferObject>().isResizable()) ||
|
||||
(buffer->is<SharedArrayBufferObject>() &&
|
||||
buffer->as<SharedArrayBufferObject>().isGrowable());
|
||||
bool lengthTracking = isResizableOrGrowable && !args.hasDefined(2);
|
||||
|
||||
if (args.length() > 1) {
|
||||
uint64_t offset;
|
||||
if (!ToIndex(cx, args[1], &offset))
|
||||
if (!ToUint32(cx, args[1], &byteOffset))
|
||||
return false;
|
||||
if (offset > INT32_MAX) {
|
||||
if (byteOffset > INT32_MAX) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE,
|
||||
"1");
|
||||
return false;
|
||||
}
|
||||
byteOffset = uint32_t(offset);
|
||||
}
|
||||
|
||||
if (buffer->is<ArrayBufferObject>() && buffer->as<ArrayBufferObject>().isDetached()) {
|
||||
if (buffer->isDetached()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2004,18 +1957,14 @@ DataViewObject::getAndCheckConstructorArgs(JSContext* cx, JSObject* bufobj, cons
|
|||
|
||||
if (args.get(2).isUndefined()) {
|
||||
byteLength -= byteOffset;
|
||||
lengthTracking = isResizableOrGrowable;
|
||||
} else {
|
||||
uint64_t viewByteLength;
|
||||
if (!ToIndex(cx, args[2], &viewByteLength))
|
||||
if (!ToUint32(cx, args[2], &byteLength))
|
||||
return false;
|
||||
lengthTracking = false;
|
||||
if (viewByteLength > INT32_MAX) {
|
||||
if (byteLength > INT32_MAX) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_ARG_INDEX_OUT_OF_RANGE, "2");
|
||||
return false;
|
||||
}
|
||||
byteLength = uint32_t(viewByteLength);
|
||||
|
||||
MOZ_ASSERT(byteOffset + byteLength >= byteOffset,
|
||||
"can't overflow: both numbers are less than INT32_MAX");
|
||||
|
|
@ -2034,7 +1983,6 @@ DataViewObject::getAndCheckConstructorArgs(JSContext* cx, JSObject* bufobj, cons
|
|||
|
||||
*byteOffsetPtr = byteOffset;
|
||||
*byteLengthPtr = byteLength;
|
||||
*lengthTrackingPtr = lengthTracking;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2046,8 +1994,7 @@ DataViewObject::constructSameCompartment(JSContext* cx, HandleObject bufobj, con
|
|||
assertSameCompartment(cx, bufobj);
|
||||
|
||||
uint32_t byteOffset, byteLength;
|
||||
bool lengthTracking;
|
||||
if (!getAndCheckConstructorArgs(cx, bufobj, args, &byteOffset, &byteLength, &lengthTracking))
|
||||
if (!getAndCheckConstructorArgs(cx, bufobj, args, &byteOffset, &byteLength))
|
||||
return false;
|
||||
|
||||
RootedObject proto(cx);
|
||||
|
|
@ -2055,9 +2002,8 @@ DataViewObject::constructSameCompartment(JSContext* cx, HandleObject bufobj, con
|
|||
if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
|
||||
return false;
|
||||
|
||||
Rooted<ArrayBufferObjectMaybeShared*> buffer(cx, &bufobj->as<ArrayBufferObjectMaybeShared>());
|
||||
JSObject* obj = DataViewObject::create(cx, byteOffset, byteLength, buffer, proto,
|
||||
lengthTracking);
|
||||
Rooted<ArrayBufferObject*> buffer(cx, &AsArrayBuffer(bufobj));
|
||||
JSObject* obj = DataViewObject::create(cx, byteOffset, byteLength, buffer, proto);
|
||||
if (!obj)
|
||||
return false;
|
||||
args.rval().setObject(*obj);
|
||||
|
|
@ -2097,12 +2043,8 @@ DataViewObject::constructWrapped(JSContext* cx, HandleObject bufobj, const CallA
|
|||
|
||||
// NB: This entails the IsArrayBuffer check
|
||||
uint32_t byteOffset, byteLength;
|
||||
bool lengthTracking;
|
||||
if (!getAndCheckConstructorArgs(cx, unwrapped, args, &byteOffset, &byteLength,
|
||||
&lengthTracking))
|
||||
{
|
||||
if (!getAndCheckConstructorArgs(cx, unwrapped, args, &byteOffset, &byteLength))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure to get the [[Prototype]] for the created view from this
|
||||
// compartment.
|
||||
|
|
@ -2118,12 +2060,11 @@ DataViewObject::constructWrapped(JSContext* cx, HandleObject bufobj, const CallA
|
|||
return false;
|
||||
}
|
||||
|
||||
FixedInvokeArgs<4> args2(cx);
|
||||
FixedInvokeArgs<3> args2(cx);
|
||||
|
||||
args2[0].set(PrivateUint32Value(byteOffset));
|
||||
args2[1].set(PrivateUint32Value(byteLength));
|
||||
args2[2].setObject(*proto);
|
||||
args2[3].setBoolean(lengthTracking);
|
||||
|
||||
RootedValue fval(cx, global->createDataViewForThis());
|
||||
RootedValue thisv(cx, ObjectValue(*bufobj));
|
||||
|
|
@ -2151,11 +2092,6 @@ template <typename NativeType>
|
|||
/* static */ uint8_t*
|
||||
DataViewObject::getDataPointer(JSContext* cx, Handle<DataViewObject*> obj, uint64_t offset)
|
||||
{
|
||||
if (obj->isOutOfBounds()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DATA_VIEW_OUT_OF_BOUNDS);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const size_t TypeSize = sizeof(NativeType);
|
||||
if (offset > UINT32_MAX - TypeSize || offset + TypeSize > obj->byteLength()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE,
|
||||
|
|
@ -2319,7 +2255,7 @@ DataViewObject::read(JSContext* cx, Handle<DataViewObject*> obj,
|
|||
bool isLittleEndian = args.length() >= 2 && ToBoolean(args[1]);
|
||||
|
||||
// Steps 6-7.
|
||||
if (obj->arrayBufferEither().isDetached()) {
|
||||
if (obj->arrayBuffer().isDetached()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2418,7 +2354,7 @@ DataViewObject::write(JSContext* cx, Handle<DataViewObject*> obj,
|
|||
bool isLittleEndian = args.length() >= 3 && ToBoolean(args[2]);
|
||||
|
||||
// Steps 7-8.
|
||||
if (obj->arrayBufferEither().isDetached()) {
|
||||
if (obj->arrayBuffer().isDetached()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -3243,13 +3179,7 @@ template<Value ValueGetter(DataViewObject* view)>
|
|||
bool
|
||||
DataViewObject::getterImpl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
Rooted<DataViewObject*> view(cx, &args.thisv().toObject().as<DataViewObject>());
|
||||
if (ValueGetter != bufferValue && view->isOutOfBounds()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DATA_VIEW_OUT_OF_BOUNDS);
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().set(ValueGetter(view));
|
||||
args.rval().set(ValueGetter(&args.thisv().toObject().as<DataViewObject>()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,8 +52,6 @@ class TypedArrayObject : public NativeObject
|
|||
"right buffer slot");
|
||||
|
||||
// Slot containing length of the view in number of typed elements.
|
||||
// Length-tracking views on resizable/growable buffers store
|
||||
// LENGTH_TRACKING here and compute their visible length from the buffer.
|
||||
static const size_t LENGTH_SLOT = 1;
|
||||
static_assert(LENGTH_SLOT == JS_TYPEDARRAYLAYOUT_LENGTH_SLOT,
|
||||
"self-hosted code with burned-in constants must get the "
|
||||
|
|
@ -67,8 +65,6 @@ class TypedArrayObject : public NativeObject
|
|||
|
||||
static const size_t RESERVED_SLOTS = 3;
|
||||
|
||||
static const int32_t LENGTH_TRACKING = -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
static const uint8_t ZeroLengthArrayData = 0x4A;
|
||||
#endif
|
||||
|
|
@ -143,13 +139,15 @@ class TypedArrayObject : public NativeObject
|
|||
return tarr->getFixedSlot(BUFFER_SLOT);
|
||||
}
|
||||
static Value byteOffsetValue(TypedArrayObject* tarr) {
|
||||
return Int32Value(tarr->byteOffset());
|
||||
Value v = tarr->getFixedSlot(BYTEOFFSET_SLOT);
|
||||
MOZ_ASSERT(v.toInt32() >= 0);
|
||||
return v;
|
||||
}
|
||||
static Value byteLengthValue(TypedArrayObject* tarr) {
|
||||
return Int32Value(tarr->byteLength());
|
||||
return Int32Value(tarr->getFixedSlot(LENGTH_SLOT).toInt32() * tarr->bytesPerElement());
|
||||
}
|
||||
static Value lengthValue(TypedArrayObject* tarr) {
|
||||
return Int32Value(tarr->length());
|
||||
return tarr->getFixedSlot(LENGTH_SLOT);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -161,70 +159,14 @@ class TypedArrayObject : public NativeObject
|
|||
JSObject* bufferObject() const {
|
||||
return bufferValue(const_cast<TypedArrayObject*>(this)).toObjectOrNull();
|
||||
}
|
||||
bool isLengthTracking() const {
|
||||
return getFixedSlot(LENGTH_SLOT).toInt32() == LENGTH_TRACKING;
|
||||
}
|
||||
bool hasResizableOrGrowableBuffer() const {
|
||||
if (!hasBuffer())
|
||||
return false;
|
||||
if (isSharedMemory())
|
||||
return bufferShared()->isGrowable();
|
||||
return bufferUnshared()->isResizable();
|
||||
}
|
||||
uint32_t byteOffsetMaybeOutOfBounds() const {
|
||||
Value v = getFixedSlot(BYTEOFFSET_SLOT);
|
||||
MOZ_ASSERT(v.toInt32() >= 0);
|
||||
return v.toInt32();
|
||||
}
|
||||
uint32_t fixedLengthMaybeOutOfBounds() const {
|
||||
int32_t length = getFixedSlot(LENGTH_SLOT).toInt32();
|
||||
MOZ_ASSERT(length >= 0);
|
||||
return length;
|
||||
}
|
||||
uint32_t bufferByteLength() const {
|
||||
MOZ_ASSERT(hasBuffer());
|
||||
if (isSharedMemory())
|
||||
return bufferShared()->byteLength();
|
||||
return bufferUnshared()->byteLength();
|
||||
}
|
||||
bool isOutOfBounds() const {
|
||||
if (!hasBuffer())
|
||||
return false;
|
||||
if (hasDetachedBuffer())
|
||||
return true;
|
||||
|
||||
uint32_t bufferByteLength = this->bufferByteLength();
|
||||
uint32_t offset = byteOffsetMaybeOutOfBounds();
|
||||
if (offset > bufferByteLength)
|
||||
return true;
|
||||
|
||||
if (isLengthTracking())
|
||||
return false;
|
||||
|
||||
uint32_t byteLength = fixedLengthMaybeOutOfBounds() * bytesPerElement();
|
||||
return byteLength > bufferByteLength - offset;
|
||||
}
|
||||
uint32_t byteOffset() const {
|
||||
if (isOutOfBounds())
|
||||
return 0;
|
||||
return byteOffsetMaybeOutOfBounds();
|
||||
return byteOffsetValue(const_cast<TypedArrayObject*>(this)).toInt32();
|
||||
}
|
||||
uint32_t byteLength() const {
|
||||
return length() * bytesPerElement();
|
||||
return byteLengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
|
||||
}
|
||||
uint32_t length() const {
|
||||
if (!isLengthTracking()) {
|
||||
if (isOutOfBounds())
|
||||
return 0;
|
||||
return fixedLengthMaybeOutOfBounds();
|
||||
}
|
||||
|
||||
if (isOutOfBounds())
|
||||
return 0;
|
||||
|
||||
uint32_t bufferByteLength = this->bufferByteLength();
|
||||
uint32_t offset = byteOffsetMaybeOutOfBounds();
|
||||
return (bufferByteLength - offset) / bytesPerElement();
|
||||
return lengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
|
||||
}
|
||||
|
||||
bool hasInlineElements() const;
|
||||
|
|
@ -524,26 +466,28 @@ class DataViewObject : public NativeObject
|
|||
defineGetter(JSContext* cx, PropertyName* name, HandleNativeObject proto);
|
||||
|
||||
static bool getAndCheckConstructorArgs(JSContext* cx, JSObject* bufobj, const CallArgs& args,
|
||||
uint32_t *byteOffset, uint32_t* byteLength,
|
||||
bool* lengthTracking);
|
||||
uint32_t *byteOffset, uint32_t* byteLength);
|
||||
static bool constructSameCompartment(JSContext* cx, HandleObject bufobj, const CallArgs& args);
|
||||
static bool constructWrapped(JSContext* cx, HandleObject bufobj, const CallArgs& args);
|
||||
|
||||
friend bool ArrayBufferObject::createDataViewForThisImpl(JSContext* cx, const CallArgs& args);
|
||||
static DataViewObject*
|
||||
create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
|
||||
Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, JSObject* proto,
|
||||
bool lengthTracking = false);
|
||||
Handle<ArrayBufferObject*> arrayBuffer, JSObject* proto);
|
||||
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
static Value byteOffsetValue(DataViewObject* view) {
|
||||
return Int32Value(view->byteOffset());
|
||||
Value v = view->getFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT);
|
||||
MOZ_ASSERT(v.toInt32() >= 0);
|
||||
return v;
|
||||
}
|
||||
|
||||
static Value byteLengthValue(DataViewObject* view) {
|
||||
return Int32Value(view->byteLength());
|
||||
Value v = view->getFixedSlot(TypedArrayObject::LENGTH_SLOT);
|
||||
MOZ_ASSERT(v.toInt32() >= 0);
|
||||
return v;
|
||||
}
|
||||
|
||||
static Value bufferValue(DataViewObject* view) {
|
||||
|
|
@ -551,66 +495,21 @@ class DataViewObject : public NativeObject
|
|||
}
|
||||
|
||||
uint32_t byteOffset() const {
|
||||
if (isOutOfBounds())
|
||||
return 0;
|
||||
return byteOffsetMaybeOutOfBounds();
|
||||
return byteOffsetValue(const_cast<DataViewObject*>(this)).toInt32();
|
||||
}
|
||||
|
||||
uint32_t byteLength() const {
|
||||
if (isOutOfBounds())
|
||||
return 0;
|
||||
if (isLengthTracking())
|
||||
return arrayBufferEither().byteLength() - byteOffsetMaybeOutOfBounds();
|
||||
return fixedByteLengthMaybeOutOfBounds();
|
||||
return byteLengthValue(const_cast<DataViewObject*>(this)).toInt32();
|
||||
}
|
||||
|
||||
ArrayBufferObjectMaybeShared& arrayBufferEither() const {
|
||||
return bufferValue(const_cast<DataViewObject*>(this)).
|
||||
toObject().as<ArrayBufferObjectMaybeShared>();
|
||||
}
|
||||
|
||||
bool isSharedMemory() const {
|
||||
return bufferValue(const_cast<DataViewObject*>(this)).
|
||||
toObject().is<SharedArrayBufferObject>();
|
||||
ArrayBufferObject& arrayBuffer() const {
|
||||
return bufferValue(const_cast<DataViewObject*>(this)).toObject().as<ArrayBufferObject>();
|
||||
}
|
||||
|
||||
void* dataPointer() const {
|
||||
return getPrivate();
|
||||
}
|
||||
|
||||
bool isLengthTracking() const {
|
||||
return getFixedSlot(TypedArrayObject::LENGTH_SLOT).toInt32() ==
|
||||
TypedArrayObject::LENGTH_TRACKING;
|
||||
}
|
||||
|
||||
uint32_t byteOffsetMaybeOutOfBounds() const {
|
||||
Value v = getFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT);
|
||||
MOZ_ASSERT(v.toInt32() >= 0);
|
||||
return v.toInt32();
|
||||
}
|
||||
|
||||
uint32_t fixedByteLengthMaybeOutOfBounds() const {
|
||||
int32_t length = getFixedSlot(TypedArrayObject::LENGTH_SLOT).toInt32();
|
||||
MOZ_ASSERT(length >= 0);
|
||||
return length;
|
||||
}
|
||||
|
||||
bool isOutOfBounds() const {
|
||||
const ArrayBufferObjectMaybeShared& buffer = arrayBufferEither();
|
||||
if (buffer.isDetached())
|
||||
return true;
|
||||
|
||||
uint32_t bufferByteLength = buffer.byteLength();
|
||||
uint32_t offset = byteOffsetMaybeOutOfBounds();
|
||||
if (offset > bufferByteLength)
|
||||
return true;
|
||||
|
||||
if (isLengthTracking())
|
||||
return false;
|
||||
|
||||
return fixedByteLengthMaybeOutOfBounds() > bufferByteLength - offset;
|
||||
}
|
||||
|
||||
static bool class_constructor(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static bool getInt8Impl(JSContext* cx, const CallArgs& args);
|
||||
|
|
|
|||
|
|
@ -1446,7 +1446,6 @@ ReloadPrefsCallback(const char* pref, void* data)
|
|||
bool extraWarnings = Preferences::GetBool(JS_OPTIONS_DOT_STR "strict");
|
||||
|
||||
bool streams = Preferences::GetBool(JS_OPTIONS_DOT_STR "streams");
|
||||
bool weakRefs = Preferences::GetBool(JS_OPTIONS_DOT_STR "weakrefs");
|
||||
|
||||
bool unboxedObjects = Preferences::GetBool(JS_OPTIONS_DOT_STR "unboxed_objects");
|
||||
|
||||
|
|
@ -1473,8 +1472,7 @@ ReloadPrefsCallback(const char* pref, void* data)
|
|||
.setWerror(werror)
|
||||
.setExtraWarnings(extraWarnings)
|
||||
.setArrayProtoValues(arrayProtoValues)
|
||||
.setStreams(streams)
|
||||
.setWeakRefs(weakRefs);
|
||||
.setStreams(streams);
|
||||
|
||||
JS_SetParallelParsingEnabled(cx, parallelParsing);
|
||||
JS_SetOffthreadIonCompilationEnabled(cx, offthreadIonCompilation);
|
||||
|
|
|
|||
|
|
@ -1,960 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CSSNestingFlattener.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
|
||||
namespace {
|
||||
|
||||
class CSSNestingFlattener final
|
||||
{
|
||||
using SelectorList = nsTArray<nsString>;
|
||||
|
||||
public:
|
||||
explicit CSSNestingFlattener(const nsAString& aInput)
|
||||
: mInput(aInput)
|
||||
, mPos(0)
|
||||
, mSawNesting(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool Flatten(nsAString& aOutput)
|
||||
{
|
||||
nsAutoString flattened;
|
||||
if (!ProcessStylesheet(flattened, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkipWhitespaceAndComments();
|
||||
if (mPos != mInput.Length() || !mSawNesting) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aOutput.Assign(flattened);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool
|
||||
IsCSSWhitespace(char16_t aChar)
|
||||
{
|
||||
return aChar == ' ' || aChar == '\t' || aChar == '\r' ||
|
||||
aChar == '\n' || aChar == '\f';
|
||||
}
|
||||
|
||||
bool
|
||||
AtEnd() const
|
||||
{
|
||||
return mPos >= mInput.Length();
|
||||
}
|
||||
|
||||
char16_t
|
||||
Peek() const
|
||||
{
|
||||
MOZ_ASSERT(!AtEnd(), "cannot peek past end");
|
||||
return mInput.CharAt(mPos);
|
||||
}
|
||||
|
||||
bool
|
||||
StartsWithComment() const
|
||||
{
|
||||
return mPos + 1 < mInput.Length() &&
|
||||
mInput.CharAt(mPos) == '/' &&
|
||||
mInput.CharAt(mPos + 1) == '*';
|
||||
}
|
||||
|
||||
bool
|
||||
SkipComment()
|
||||
{
|
||||
MOZ_ASSERT(StartsWithComment(), "expected comment");
|
||||
|
||||
mPos += 2;
|
||||
while (mPos + 1 < mInput.Length()) {
|
||||
if (mInput.CharAt(mPos) == '*' && mInput.CharAt(mPos + 1) == '/') {
|
||||
mPos += 2;
|
||||
return true;
|
||||
}
|
||||
++mPos;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SkipWhitespaceAndComments()
|
||||
{
|
||||
while (!AtEnd()) {
|
||||
if (IsCSSWhitespace(Peek())) {
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (StartsWithComment()) {
|
||||
if (!SkipComment()) {
|
||||
mPos = mInput.Length();
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SkipString(char16_t aQuote)
|
||||
{
|
||||
MOZ_ASSERT(!AtEnd() && Peek() == aQuote, "expected string start");
|
||||
|
||||
++mPos;
|
||||
while (!AtEnd()) {
|
||||
char16_t c = Peek();
|
||||
++mPos;
|
||||
if (c == aQuote) {
|
||||
return true;
|
||||
}
|
||||
if (c == '\\' && !AtEnd()) {
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == '\n' || c == '\r' || c == '\f') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
TrimWhitespace(nsAString& aText)
|
||||
{
|
||||
uint32_t start = 0;
|
||||
uint32_t end = aText.Length();
|
||||
|
||||
while (start < end && IsCSSWhitespace(aText.CharAt(start))) {
|
||||
++start;
|
||||
}
|
||||
while (end > start && IsCSSWhitespace(aText.CharAt(end - 1))) {
|
||||
--end;
|
||||
}
|
||||
|
||||
if (start == 0 && end == aText.Length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aText.Assign(Substring(aText, start, end - start));
|
||||
}
|
||||
|
||||
bool
|
||||
SplitSelectorList(const nsAString& aSelectorText, SelectorList& aSelectors)
|
||||
{
|
||||
uint32_t itemStart = 0;
|
||||
int32_t parenDepth = 0;
|
||||
int32_t bracketDepth = 0;
|
||||
bool inComment = false;
|
||||
char16_t stringQuote = 0;
|
||||
|
||||
for (uint32_t i = 0; i < aSelectorText.Length(); ++i) {
|
||||
char16_t c = aSelectorText.CharAt(i);
|
||||
|
||||
if (inComment) {
|
||||
if (c == '*' && i + 1 < aSelectorText.Length() &&
|
||||
aSelectorText.CharAt(i + 1) == '/') {
|
||||
inComment = false;
|
||||
++i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stringQuote) {
|
||||
if (c == '\\') {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (c == stringQuote) {
|
||||
stringQuote = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '/' && i + 1 < aSelectorText.Length() &&
|
||||
aSelectorText.CharAt(i + 1) == '*') {
|
||||
inComment = true;
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '"' || c == '\'') {
|
||||
stringQuote = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '(') {
|
||||
++parenDepth;
|
||||
continue;
|
||||
}
|
||||
if (c == ')' && parenDepth > 0) {
|
||||
--parenDepth;
|
||||
continue;
|
||||
}
|
||||
if (c == '[') {
|
||||
++bracketDepth;
|
||||
continue;
|
||||
}
|
||||
if (c == ']' && bracketDepth > 0) {
|
||||
--bracketDepth;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == ',' && parenDepth == 0 && bracketDepth == 0) {
|
||||
nsAutoString selector;
|
||||
selector.Assign(Substring(aSelectorText, itemStart, i - itemStart));
|
||||
TrimWhitespace(selector);
|
||||
if (!selector.IsEmpty()) {
|
||||
aSelectors.AppendElement(selector);
|
||||
}
|
||||
itemStart = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString selector;
|
||||
selector.Assign(Substring(aSelectorText, itemStart));
|
||||
TrimWhitespace(selector);
|
||||
if (!selector.IsEmpty()) {
|
||||
aSelectors.AppendElement(selector);
|
||||
}
|
||||
|
||||
return !aSelectors.IsEmpty();
|
||||
}
|
||||
|
||||
bool
|
||||
SelectorHasAmpersand(const nsAString& aSelector) const
|
||||
{
|
||||
bool inComment = false;
|
||||
char16_t stringQuote = 0;
|
||||
|
||||
for (uint32_t i = 0; i < aSelector.Length(); ++i) {
|
||||
char16_t c = aSelector.CharAt(i);
|
||||
|
||||
if (inComment) {
|
||||
if (c == '*' && i + 1 < aSelector.Length() &&
|
||||
aSelector.CharAt(i + 1) == '/') {
|
||||
inComment = false;
|
||||
++i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stringQuote) {
|
||||
if (c == '\\') {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (c == stringQuote) {
|
||||
stringQuote = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '/' && i + 1 < aSelector.Length() &&
|
||||
aSelector.CharAt(i + 1) == '*') {
|
||||
inComment = true;
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '"' || c == '\'') {
|
||||
stringQuote = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '&') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ReplaceAmpersands(const nsAString& aSelector,
|
||||
const nsAString& aParent,
|
||||
nsAString& aOutput) const
|
||||
{
|
||||
bool inComment = false;
|
||||
char16_t stringQuote = 0;
|
||||
|
||||
for (uint32_t i = 0; i < aSelector.Length(); ++i) {
|
||||
char16_t c = aSelector.CharAt(i);
|
||||
|
||||
if (inComment) {
|
||||
aOutput.Append(c);
|
||||
if (c == '*' && i + 1 < aSelector.Length() &&
|
||||
aSelector.CharAt(i + 1) == '/') {
|
||||
aOutput.Append('/');
|
||||
inComment = false;
|
||||
++i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stringQuote) {
|
||||
aOutput.Append(c);
|
||||
if (c == '\\' && i + 1 < aSelector.Length()) {
|
||||
aOutput.Append(aSelector.CharAt(i + 1));
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (c == stringQuote) {
|
||||
stringQuote = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '/' && i + 1 < aSelector.Length() &&
|
||||
aSelector.CharAt(i + 1) == '*') {
|
||||
aOutput.AppendLiteral("/*");
|
||||
inComment = true;
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '"' || c == '\'') {
|
||||
aOutput.Append(c);
|
||||
stringQuote = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '&') {
|
||||
aOutput.Append(aParent);
|
||||
continue;
|
||||
}
|
||||
|
||||
aOutput.Append(c);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ExpandNestedSelectors(const SelectorList& aParents,
|
||||
const nsAString& aNestedSelectorText,
|
||||
SelectorList& aSelectors)
|
||||
{
|
||||
SelectorList nestedSelectors;
|
||||
if (!SplitSelectorList(aNestedSelectorText, nestedSelectors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const nsString& nestedSelector : nestedSelectors) {
|
||||
bool hasAmpersand = SelectorHasAmpersand(nestedSelector);
|
||||
for (const nsString& parentSelector : aParents) {
|
||||
nsAutoString combined;
|
||||
if (hasAmpersand) {
|
||||
ReplaceAmpersands(nestedSelector, parentSelector, combined);
|
||||
} else {
|
||||
combined.Assign(parentSelector);
|
||||
if (!combined.IsEmpty()) {
|
||||
combined.Append(' ');
|
||||
}
|
||||
combined.Append(nestedSelector);
|
||||
}
|
||||
TrimWhitespace(combined);
|
||||
if (!combined.IsEmpty()) {
|
||||
aSelectors.AppendElement(combined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !aSelectors.IsEmpty();
|
||||
}
|
||||
|
||||
static void
|
||||
AppendSelectors(const SelectorList& aSelectors, nsAString& aOutput)
|
||||
{
|
||||
for (uint32_t i = 0; i < aSelectors.Length(); ++i) {
|
||||
if (i) {
|
||||
aOutput.AppendLiteral(", ");
|
||||
}
|
||||
aOutput.Append(aSelectors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
StartsNestedSelector(char16_t aChar)
|
||||
{
|
||||
switch (aChar) {
|
||||
case '.':
|
||||
case '#':
|
||||
case '[':
|
||||
case ':':
|
||||
case '&':
|
||||
case '|':
|
||||
case '>':
|
||||
case '+':
|
||||
case '~':
|
||||
case '*':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
StartsPotentialTypeSelector(char16_t aChar)
|
||||
{
|
||||
return (aChar >= 'a' && aChar <= 'z') ||
|
||||
(aChar >= 'A' && aChar <= 'Z') ||
|
||||
aChar == '_' ||
|
||||
aChar == '\\' ||
|
||||
aChar >= 0x80;
|
||||
}
|
||||
|
||||
bool
|
||||
LooksLikeTypeSelectorRule() const
|
||||
{
|
||||
if (AtEnd() || !StartsPotentialTypeSelector(Peek())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t pos = mPos;
|
||||
int32_t parenDepth = 0;
|
||||
int32_t bracketDepth = 0;
|
||||
bool inComment = false;
|
||||
char16_t stringQuote = 0;
|
||||
|
||||
while (pos < mInput.Length()) {
|
||||
char16_t c = mInput.CharAt(pos);
|
||||
|
||||
if (inComment) {
|
||||
if (c == '*' && pos + 1 < mInput.Length() &&
|
||||
mInput.CharAt(pos + 1) == '/') {
|
||||
inComment = false;
|
||||
++pos;
|
||||
}
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stringQuote) {
|
||||
if (c == '\\' && pos + 1 < mInput.Length()) {
|
||||
pos += 2;
|
||||
continue;
|
||||
}
|
||||
if (c == stringQuote) {
|
||||
stringQuote = 0;
|
||||
}
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '/' && pos + 1 < mInput.Length() &&
|
||||
mInput.CharAt(pos + 1) == '*') {
|
||||
inComment = true;
|
||||
pos += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '"' || c == '\'') {
|
||||
stringQuote = c;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '(') {
|
||||
++parenDepth;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
if (c == ')' && parenDepth > 0) {
|
||||
--parenDepth;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
if (c == '[') {
|
||||
++bracketDepth;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
if (c == ']' && bracketDepth > 0) {
|
||||
--bracketDepth;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parenDepth == 0 && bracketDepth == 0) {
|
||||
if (c == '{') {
|
||||
return true;
|
||||
}
|
||||
if (c == ';' || c == '}') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
++pos;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsAtRuleNameChar(char16_t aChar)
|
||||
{
|
||||
return (aChar >= 'a' && aChar <= 'z') ||
|
||||
(aChar >= 'A' && aChar <= 'Z') ||
|
||||
(aChar >= '0' && aChar <= '9') ||
|
||||
aChar == '-';
|
||||
}
|
||||
|
||||
static void
|
||||
LowercaseASCII(nsACString& aText)
|
||||
{
|
||||
for (uint32_t i = 0; i < aText.Length(); ++i) {
|
||||
char c = aText.CharAt(i);
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
aText.BeginWriting()[i] = c - 'A' + 'a';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ShouldProcessGroupRule(const nsACString& aName)
|
||||
{
|
||||
return aName.EqualsLiteral("media") ||
|
||||
aName.EqualsLiteral("supports") ||
|
||||
aName.EqualsLiteral("document") ||
|
||||
aName.EqualsLiteral("layer");
|
||||
}
|
||||
|
||||
void
|
||||
FlushDeclarations(const SelectorList& aSelectors,
|
||||
nsAString& aDeclarations,
|
||||
nsAString& aOutput)
|
||||
{
|
||||
nsAutoString declarations;
|
||||
declarations.Assign(aDeclarations);
|
||||
TrimWhitespace(declarations);
|
||||
aDeclarations.Truncate();
|
||||
|
||||
if (declarations.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AppendSelectors(aSelectors, aOutput);
|
||||
aOutput.AppendLiteral(" { ");
|
||||
aOutput.Append(declarations);
|
||||
aOutput.AppendLiteral(" }\n");
|
||||
}
|
||||
|
||||
bool
|
||||
ReadRawBlockBody(nsAString& aBody)
|
||||
{
|
||||
uint32_t start = mPos;
|
||||
int32_t depth = 0;
|
||||
|
||||
while (!AtEnd()) {
|
||||
char16_t c = Peek();
|
||||
if (c == '"' || c == '\'') {
|
||||
if (!SkipString(c)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (StartsWithComment()) {
|
||||
if (!SkipComment()) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '{') {
|
||||
++depth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == '}') {
|
||||
if (depth == 0) {
|
||||
aBody.Assign(Substring(mInput, start, mPos - start));
|
||||
++mPos;
|
||||
return true;
|
||||
}
|
||||
--depth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
++mPos;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ReadQualifiedRulePrelude(nsAString& aPrelude)
|
||||
{
|
||||
uint32_t start = mPos;
|
||||
int32_t parenDepth = 0;
|
||||
int32_t bracketDepth = 0;
|
||||
|
||||
while (!AtEnd()) {
|
||||
char16_t c = Peek();
|
||||
if (c == '"' || c == '\'') {
|
||||
if (!SkipString(c)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (StartsWithComment()) {
|
||||
if (!SkipComment()) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '(') {
|
||||
++parenDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == ')' && parenDepth > 0) {
|
||||
--parenDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == '[') {
|
||||
++bracketDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == ']' && bracketDepth > 0) {
|
||||
--bracketDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == '{' && parenDepth == 0 && bracketDepth == 0) {
|
||||
aPrelude.Assign(Substring(mInput, start, mPos - start));
|
||||
TrimWhitespace(aPrelude);
|
||||
++mPos;
|
||||
return !aPrelude.IsEmpty();
|
||||
}
|
||||
if ((c == ';' || c == '}') && parenDepth == 0 && bracketDepth == 0) {
|
||||
return false;
|
||||
}
|
||||
++mPos;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ReadAtRulePrelude(nsAString& aPrelude, nsACString& aName, bool& aHasBlock)
|
||||
{
|
||||
MOZ_ASSERT(!AtEnd() && Peek() == '@', "expected at-rule");
|
||||
|
||||
uint32_t start = mPos;
|
||||
++mPos;
|
||||
aName.Truncate();
|
||||
while (!AtEnd() && IsAtRuleNameChar(Peek())) {
|
||||
char16_t c = Peek();
|
||||
aName.Append(char(c <= 0x7f ? c : '?'));
|
||||
++mPos;
|
||||
}
|
||||
LowercaseASCII(aName);
|
||||
|
||||
int32_t parenDepth = 0;
|
||||
int32_t bracketDepth = 0;
|
||||
while (!AtEnd()) {
|
||||
char16_t c = Peek();
|
||||
if (c == '"' || c == '\'') {
|
||||
if (!SkipString(c)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (StartsWithComment()) {
|
||||
if (!SkipComment()) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '(') {
|
||||
++parenDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == ')' && parenDepth > 0) {
|
||||
--parenDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == '[') {
|
||||
++bracketDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == ']' && bracketDepth > 0) {
|
||||
--bracketDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (parenDepth == 0 && bracketDepth == 0) {
|
||||
if (c == ';') {
|
||||
aPrelude.Assign(Substring(mInput, start, mPos - start));
|
||||
TrimWhitespace(aPrelude);
|
||||
++mPos;
|
||||
aHasBlock = false;
|
||||
return true;
|
||||
}
|
||||
if (c == '{') {
|
||||
aPrelude.Assign(Substring(mInput, start, mPos - start));
|
||||
TrimWhitespace(aPrelude);
|
||||
++mPos;
|
||||
aHasBlock = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
++mPos;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ConsumeDeclaration(nsAString& aDeclaration)
|
||||
{
|
||||
uint32_t start = mPos;
|
||||
int32_t parenDepth = 0;
|
||||
int32_t bracketDepth = 0;
|
||||
int32_t braceDepth = 0;
|
||||
|
||||
while (!AtEnd()) {
|
||||
char16_t c = Peek();
|
||||
if (c == '"' || c == '\'') {
|
||||
if (!SkipString(c)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (StartsWithComment()) {
|
||||
if (!SkipComment()) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '(') {
|
||||
++parenDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == ')' && parenDepth > 0) {
|
||||
--parenDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == '[') {
|
||||
++bracketDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == ']' && bracketDepth > 0) {
|
||||
--bracketDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == '{') {
|
||||
++braceDepth;
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == '}') {
|
||||
if (braceDepth == 0 && parenDepth == 0 && bracketDepth == 0) {
|
||||
break;
|
||||
}
|
||||
if (braceDepth > 0) {
|
||||
--braceDepth;
|
||||
}
|
||||
++mPos;
|
||||
continue;
|
||||
}
|
||||
if (c == ';' && parenDepth == 0 && bracketDepth == 0 &&
|
||||
braceDepth == 0) {
|
||||
++mPos;
|
||||
break;
|
||||
}
|
||||
++mPos;
|
||||
}
|
||||
|
||||
aDeclaration.Assign(Substring(mInput, start, mPos - start));
|
||||
TrimWhitespace(aDeclaration);
|
||||
if (aDeclaration.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (aDeclaration.Last() != ';') {
|
||||
aDeclaration.Append(';');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ParseAtRule(nsAString& aOutput, const SelectorList* aParents)
|
||||
{
|
||||
nsAutoString prelude;
|
||||
nsAutoCString name;
|
||||
bool hasBlock = false;
|
||||
if (!ReadAtRulePrelude(prelude, name, hasBlock)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasBlock) {
|
||||
aOutput.Append(prelude);
|
||||
aOutput.AppendLiteral(";\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ShouldProcessGroupRule(name)) {
|
||||
nsAutoString body;
|
||||
if (!ReadRawBlockBody(body)) {
|
||||
return false;
|
||||
}
|
||||
aOutput.Append(prelude);
|
||||
aOutput.AppendLiteral(" {");
|
||||
aOutput.Append(body);
|
||||
aOutput.AppendLiteral("}\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
nsAutoString inner;
|
||||
if (aParents) {
|
||||
mSawNesting = true;
|
||||
if (!ProcessStyleContext(*aParents, inner)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!ProcessStylesheet(inner, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
aOutput.Append(prelude);
|
||||
aOutput.AppendLiteral(" {\n");
|
||||
aOutput.Append(inner);
|
||||
aOutput.AppendLiteral("}\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ParseQualifiedRule(nsAString& aOutput, const SelectorList* aParents)
|
||||
{
|
||||
nsAutoString prelude;
|
||||
if (!ReadQualifiedRulePrelude(prelude)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SelectorList selectors;
|
||||
if (aParents) {
|
||||
mSawNesting = true;
|
||||
if (!ExpandNestedSelectors(*aParents, prelude, selectors)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!SplitSelectorList(prelude, selectors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ProcessStyleContext(selectors, aOutput);
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessStyleContext(const SelectorList& aSelectors, nsAString& aOutput)
|
||||
{
|
||||
nsAutoString declarations;
|
||||
|
||||
while (!AtEnd()) {
|
||||
SkipWhitespaceAndComments();
|
||||
if (AtEnd()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char16_t c = Peek();
|
||||
if (c == '}') {
|
||||
++mPos;
|
||||
FlushDeclarations(aSelectors, declarations, aOutput);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c == '@') {
|
||||
FlushDeclarations(aSelectors, declarations, aOutput);
|
||||
if (!ParseAtRule(aOutput, &aSelectors)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (StartsNestedSelector(c) || LooksLikeTypeSelectorRule()) {
|
||||
FlushDeclarations(aSelectors, declarations, aOutput);
|
||||
if (!ParseQualifiedRule(aOutput, &aSelectors)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString declaration;
|
||||
if (!ConsumeDeclaration(declaration)) {
|
||||
return false;
|
||||
}
|
||||
if (!declarations.IsEmpty()) {
|
||||
declarations.Append(' ');
|
||||
}
|
||||
declarations.Append(declaration);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessStylesheet(nsAString& aOutput, bool aStopAtBlockEnd)
|
||||
{
|
||||
while (!AtEnd()) {
|
||||
SkipWhitespaceAndComments();
|
||||
if (AtEnd()) {
|
||||
return !aStopAtBlockEnd;
|
||||
}
|
||||
|
||||
if (Peek() == '}') {
|
||||
if (!aStopAtBlockEnd) {
|
||||
return false;
|
||||
}
|
||||
++mPos;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Peek() == '@') {
|
||||
if (!ParseAtRule(aOutput, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!ParseQualifiedRule(aOutput, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !aStopAtBlockEnd;
|
||||
}
|
||||
|
||||
const nsAString& mInput;
|
||||
uint32_t mPos;
|
||||
bool mSawNesting;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
FlattenBasicCSSNesting(const nsAString& aInput, nsAString& aOutput)
|
||||
{
|
||||
CSSNestingFlattener flattener(aInput);
|
||||
return flattener.Flatten(aOutput);
|
||||
}
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CSSNestingFlattener_h
|
||||
#define CSSNestingFlattener_h
|
||||
|
||||
class nsAString;
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
|
||||
bool FlattenBasicCSSNesting(const nsAString& aInput, nsAString& aOutput);
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // CSSNestingFlattener_h
|
||||
|
|
@ -885,10 +885,9 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
|||
}
|
||||
|
||||
// In standards mode, a style sheet must have one of these MIME
|
||||
// types to be processed at all, unless it is same-origin.
|
||||
// For same-origin sheets, we accept any MIME type to match modern
|
||||
// browser behavior (Chrome, Firefox). Cross-origin sheets require
|
||||
// a valid CSS MIME type for security.
|
||||
// types to be processed at all. In quirks mode, we accept any
|
||||
// MIME type, but only if the style sheet is same-origin with the
|
||||
// requesting document or parent sheet. See bug 524223.
|
||||
|
||||
bool validType = contentType.EqualsLiteral("text/css") ||
|
||||
contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE) ||
|
||||
|
|
@ -907,7 +906,7 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
|||
}
|
||||
}
|
||||
|
||||
if (sameOrigin) {
|
||||
if (sameOrigin && mLoader->mCompatMode == eCompatibility_NavQuirks) {
|
||||
errorMessage = "MimeNotCssWarn";
|
||||
errorFlag = nsIScriptError::warningFlag;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@ UNIFIED_SOURCES += [
|
|||
'CounterStyleManager.cpp',
|
||||
'CSS.cpp',
|
||||
'CSSLexer.cpp',
|
||||
'CSSNestingFlattener.cpp',
|
||||
'CSSRuleList.cpp',
|
||||
'CSSStyleSheet.cpp',
|
||||
'CSSVariableDeclarations.cpp',
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
|
|
@ -18,7 +17,6 @@
|
|||
#include <regex> // for std::regex and std::regex_match
|
||||
|
||||
#include "nsCSSParser.h"
|
||||
#include "CSSNestingFlattener.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsCSSKeywords.h"
|
||||
|
|
@ -73,7 +71,6 @@ static bool sMozGradientsEnabled;
|
|||
static bool sControlCharVisibility;
|
||||
static bool sLegacyNegationPseudoClassEnabled;
|
||||
static bool sCascadeLayersEnabled;
|
||||
static bool sNestingEnabled;
|
||||
|
||||
const uint32_t
|
||||
nsCSSProps::kParserVariantTable[eCSSProperty_COUNT_no_shorthands] = {
|
||||
|
|
@ -1826,14 +1823,7 @@ CSSParserImpl::ParseSheet(const nsAString& aInput,
|
|||
"Sheet principal does not match passed principal");
|
||||
#endif
|
||||
|
||||
nsAutoString flattenedInput;
|
||||
const nsAString* input = &aInput;
|
||||
if (sNestingEnabled &&
|
||||
mozilla::css::FlattenBasicCSSNesting(aInput, flattenedInput)) {
|
||||
input = &flattenedInput;
|
||||
}
|
||||
|
||||
nsCSSScanner scanner(*input, aLineNumber);
|
||||
nsCSSScanner scanner(aInput, aLineNumber);
|
||||
css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aSheetURI);
|
||||
InitScanner(scanner, reporter, aSheetURI, aBaseURI, aSheetPrincipal);
|
||||
|
||||
|
|
@ -18997,8 +18987,6 @@ nsCSSParser::Startup()
|
|||
"layout.css.legacy-negation-pseudo.enabled");
|
||||
Preferences::AddBoolVarCache(&sCascadeLayersEnabled,
|
||||
"layout.css.cascade-layers.enabled");
|
||||
Preferences::AddBoolVarCache(&sNestingEnabled,
|
||||
"layout.css.nesting.enabled");
|
||||
}
|
||||
|
||||
nsCSSParser::nsCSSParser(mozilla::css::Loader* aLoader,
|
||||
|
|
|
|||
|
|
@ -72,9 +72,6 @@ support-files = file_animations_with_disabled_properties.html
|
|||
[test_attribute_selector_eof_behavior.html]
|
||||
[test_aspect_ratio_property.html]
|
||||
[test_background_blend_mode.html]
|
||||
[test_basic_nesting_flattening.html]
|
||||
[test_nesting_flattening_parser_edges.html]
|
||||
[test_nesting_flattening_recovery.html]
|
||||
[test_box_size_keywords.html]
|
||||
[test_bug73586.html]
|
||||
[test_css_math_functions.html]
|
||||
|
|
|
|||
|
|
@ -1,146 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Basic CSS Nesting Flattening</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="scope" class="scope order">
|
||||
<span id="desc" class="desc"></span>
|
||||
</div>
|
||||
<div id="button" class="button active"></div>
|
||||
<pre id="standalone-log"></pre>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
function colorOf(win, element, property) {
|
||||
return win.getComputedStyle(element).getPropertyValue(property);
|
||||
}
|
||||
|
||||
function appendTestSheet() {
|
||||
var style = document.createElement("style");
|
||||
style.textContent =
|
||||
".scope {\n" +
|
||||
" color: rgb(1, 2, 3);\n" +
|
||||
" .desc {\n" +
|
||||
" color: rgb(4, 5, 6);\n" +
|
||||
" }\n" +
|
||||
" span {\n" +
|
||||
" border-left-style: solid;\n" +
|
||||
" border-left-color: rgb(19, 20, 21);\n" +
|
||||
" }\n" +
|
||||
" span:first-child, span:last-child {\n" +
|
||||
" border-bottom-style: solid;\n" +
|
||||
" border-bottom-color: rgb(22, 23, 24);\n" +
|
||||
" }\n" +
|
||||
" background-color: rgb(7, 8, 9);\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
".button {\n" +
|
||||
" &.active {\n" +
|
||||
" color: rgb(10, 11, 12);\n" +
|
||||
" }\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
".order {\n" +
|
||||
" border-top-style: solid;\n" +
|
||||
" @media all {\n" +
|
||||
" & {\n" +
|
||||
" border-top-color: rgb(13, 14, 15);\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" border-right-style: solid;\n" +
|
||||
" border-right-color: rgb(16, 17, 18);\n" +
|
||||
"}\n";
|
||||
document.head.appendChild(style);
|
||||
return style;
|
||||
}
|
||||
|
||||
function runChecks(style, report) {
|
||||
var scope = document.getElementById("scope");
|
||||
var desc = document.getElementById("desc");
|
||||
var button = document.getElementById("button");
|
||||
|
||||
report(colorOf(window, scope, "color") === "rgb(1, 2, 3)",
|
||||
"outer rule declarations should apply",
|
||||
colorOf(window, scope, "color"),
|
||||
"rgb(1, 2, 3)");
|
||||
report(colorOf(window, desc, "color") === "rgb(4, 5, 6)",
|
||||
"nested descendant rule should be flattened",
|
||||
colorOf(window, desc, "color"),
|
||||
"rgb(4, 5, 6)");
|
||||
report(colorOf(window, desc, "border-left-color") === "rgb(19, 20, 21)",
|
||||
"nested type selector rule should be flattened",
|
||||
colorOf(window, desc, "border-left-color"),
|
||||
"rgb(19, 20, 21)");
|
||||
report(colorOf(window, desc, "border-bottom-color") === "rgb(22, 23, 24)",
|
||||
"nested type selector pseudos should be flattened",
|
||||
colorOf(window, desc, "border-bottom-color"),
|
||||
"rgb(22, 23, 24)");
|
||||
report(colorOf(window, scope, "background-color") === "rgb(7, 8, 9)",
|
||||
"declarations after a nested rule should preserve order",
|
||||
colorOf(window, scope, "background-color"),
|
||||
"rgb(7, 8, 9)");
|
||||
report(colorOf(window, button, "color") === "rgb(10, 11, 12)",
|
||||
"ampersand selectors should be expanded",
|
||||
colorOf(window, button, "color"),
|
||||
"rgb(10, 11, 12)");
|
||||
report(colorOf(window, scope, "border-top-color") === "rgb(13, 14, 15)",
|
||||
"nested group rules should target the parent selector",
|
||||
colorOf(window, scope, "border-top-color"),
|
||||
"rgb(13, 14, 15)");
|
||||
report(colorOf(window, scope, "border-right-color") === "rgb(16, 17, 18)",
|
||||
"declarations after nested group rules should still apply",
|
||||
colorOf(window, scope, "border-right-color"),
|
||||
"rgb(16, 17, 18)");
|
||||
report(style.sheet.cssRules.length === 9,
|
||||
"flattening should produce flat top-level rules",
|
||||
String(style.sheet.cssRules.length),
|
||||
"9");
|
||||
}
|
||||
|
||||
function runStandalone() {
|
||||
var log = document.getElementById("standalone-log");
|
||||
var lines = [
|
||||
"Standalone mode.",
|
||||
"This page only demonstrates nesting if layout.css.nesting.enabled is already true in the browser.",
|
||||
""
|
||||
];
|
||||
var style = appendTestSheet();
|
||||
|
||||
runChecks(style, function(pass, message, actual, expected) {
|
||||
lines.push((pass ? "PASS" : "FAIL") + ": " + message);
|
||||
if (!pass) {
|
||||
lines.push(" expected: " + expected);
|
||||
lines.push(" actual: " + actual);
|
||||
}
|
||||
});
|
||||
|
||||
log.textContent = lines.join("\n");
|
||||
}
|
||||
|
||||
function runMochitest() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({
|
||||
set: [["layout.css.nesting.enabled", true]]
|
||||
}, function() {
|
||||
var style = appendTestSheet();
|
||||
|
||||
runChecks(style, function(pass, message, actual, expected) {
|
||||
is(actual, expected, message);
|
||||
});
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof SimpleTest !== "undefined" && typeof SpecialPowers !== "undefined") {
|
||||
runMochitest();
|
||||
} else {
|
||||
runStandalone();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test CSS Nesting Flattening Parser Edges</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="scope" class="scope">
|
||||
<span id="firstSpan" class="desc"></span>
|
||||
<span id="middleSpan" class="middle"></span>
|
||||
<span id="escapedSpan" class="1foo"></span>
|
||||
<svg id="svgRoot" xmlns="http://www.w3.org/2000/svg" width="10" height="10">
|
||||
<rect id="nsRect" width="10" height="10"></rect>
|
||||
</svg>
|
||||
</div>
|
||||
<div id="afterMalformed" class="after-malformed"></div>
|
||||
<div id="afterTarget" class="after-target"></div>
|
||||
<pre id="standalone-log"></pre>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
function propOf(win, element, property) {
|
||||
return win.getComputedStyle(element).getPropertyValue(property);
|
||||
}
|
||||
|
||||
function appendTestSheet() {
|
||||
var style = document.createElement("style");
|
||||
style.textContent =
|
||||
"@namespace svg url(http://www.w3.org/2000/svg);\n" +
|
||||
".scope {\n" +
|
||||
" --payload: { alpha: 1; beta: 2; };\n" +
|
||||
" color: rgb(1, 2, 3);\n" +
|
||||
" span:first-of-type, span:last-of-type {\n" +
|
||||
" color: rgb(30, 31, 32);\n" +
|
||||
" }\n" +
|
||||
" .\\31 foo {\n" +
|
||||
" border-left-style: solid;\n" +
|
||||
" border-left-color: rgb(40, 41, 42);\n" +
|
||||
" }\n" +
|
||||
" svg|rect {\n" +
|
||||
" stroke: rgb(50, 51, 52);\n" +
|
||||
" stroke-width: 1px;\n" +
|
||||
" }\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
".after-malformed {\n" +
|
||||
" color: rgb(60, 61, 62);\n" +
|
||||
" : {\n" +
|
||||
" color: rgb(70, 71, 72);\n" +
|
||||
" }\n" +
|
||||
" background-color: rgb(80, 81, 82);\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
".after-target {\n" +
|
||||
" color: rgb(90, 91, 92);\n" +
|
||||
"}\n";
|
||||
document.head.appendChild(style);
|
||||
return style;
|
||||
}
|
||||
|
||||
function runChecks(style, report) {
|
||||
var scope = document.getElementById("scope");
|
||||
var firstSpan = document.getElementById("firstSpan");
|
||||
var middleSpan = document.getElementById("middleSpan");
|
||||
var escapedSpan = document.getElementById("escapedSpan");
|
||||
var rect = document.getElementById("nsRect");
|
||||
var afterMalformed = document.getElementById("afterMalformed");
|
||||
var afterTarget = document.getElementById("afterTarget");
|
||||
|
||||
var payload = propOf(window, scope, "--payload");
|
||||
report(payload.indexOf("alpha") !== -1 && payload.indexOf("beta") !== -1,
|
||||
"custom property payload should survive flattening",
|
||||
payload,
|
||||
"contains alpha and beta");
|
||||
|
||||
report(propOf(window, scope, "color") === "rgb(1, 2, 3)",
|
||||
"base declaration should apply",
|
||||
propOf(window, scope, "color"),
|
||||
"rgb(1, 2, 3)");
|
||||
report(propOf(window, firstSpan, "color") === "rgb(30, 31, 32)",
|
||||
"nested pseudo selector should style first span",
|
||||
propOf(window, firstSpan, "color"),
|
||||
"rgb(30, 31, 32)");
|
||||
report(propOf(window, escapedSpan, "color") === "rgb(30, 31, 32)",
|
||||
"nested pseudo selector should style last span",
|
||||
propOf(window, escapedSpan, "color"),
|
||||
"rgb(30, 31, 32)");
|
||||
report(propOf(window, middleSpan, "color") === "rgb(1, 2, 3)",
|
||||
"middle span should keep inherited scope color",
|
||||
propOf(window, middleSpan, "color"),
|
||||
"rgb(1, 2, 3)");
|
||||
|
||||
report(propOf(window, escapedSpan, "border-left-color") === "rgb(40, 41, 42)",
|
||||
"escaped class selector should match",
|
||||
propOf(window, escapedSpan, "border-left-color"),
|
||||
"rgb(40, 41, 42)");
|
||||
|
||||
report(propOf(window, rect, "stroke") === "rgb(50, 51, 52)",
|
||||
"namespace selector should match nested SVG rect",
|
||||
propOf(window, rect, "stroke"),
|
||||
"rgb(50, 51, 52)");
|
||||
|
||||
report(propOf(window, afterMalformed, "color") === "rgb(60, 61, 62)",
|
||||
"declaration before malformed nested selector should apply",
|
||||
propOf(window, afterMalformed, "color"),
|
||||
"rgb(60, 61, 62)");
|
||||
report(propOf(window, afterMalformed, "background-color") === "rgb(80, 81, 82)",
|
||||
"declaration after malformed nested selector should still apply",
|
||||
propOf(window, afterMalformed, "background-color"),
|
||||
"rgb(80, 81, 82)");
|
||||
report(propOf(window, afterTarget, "color") === "rgb(90, 91, 92)",
|
||||
"subsequent top-level rules should still parse",
|
||||
propOf(window, afterTarget, "color"),
|
||||
"rgb(90, 91, 92)");
|
||||
}
|
||||
|
||||
function runStandalone() {
|
||||
var log = document.getElementById("standalone-log");
|
||||
var lines = [
|
||||
"Standalone mode.",
|
||||
"This page only demonstrates nesting if layout.css.nesting.enabled is already true in the browser.",
|
||||
""
|
||||
];
|
||||
var style = appendTestSheet();
|
||||
|
||||
runChecks(style, function(pass, message, actual, expected) {
|
||||
lines.push((pass ? "PASS" : "FAIL") + ": " + message);
|
||||
if (!pass) {
|
||||
lines.push(" expected: " + expected);
|
||||
lines.push(" actual: " + actual);
|
||||
}
|
||||
});
|
||||
|
||||
log.textContent = lines.join("\n");
|
||||
}
|
||||
|
||||
function runMochitest() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({
|
||||
set: [["layout.css.nesting.enabled", true]]
|
||||
}, function() {
|
||||
var style = appendTestSheet();
|
||||
|
||||
runChecks(style, function(pass, message, actual, expected) {
|
||||
ok(pass, message + " (expected: " + expected + ", actual: " + actual + ")");
|
||||
});
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof SimpleTest !== "undefined" && typeof SpecialPowers !== "undefined") {
|
||||
runMochitest();
|
||||
} else {
|
||||
runStandalone();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test CSS Nesting Flattening Recovery Paths</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="recBase" class="rec-base"><span id="recBaseChild"></span></div>
|
||||
<div id="recMalformed" class="rec-malformed"></div>
|
||||
<div id="recGroup" class="rec-group"></div>
|
||||
<div id="recTail" class="rec-tail"></div>
|
||||
<pre id="standalone-log"></pre>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
function propOf(win, element, property) {
|
||||
return win.getComputedStyle(element).getPropertyValue(property);
|
||||
}
|
||||
|
||||
function appendTestSheet() {
|
||||
var style = document.createElement("style");
|
||||
style.textContent =
|
||||
".rec-base {\n" +
|
||||
" color: rgb(1, 2, 3);\n" +
|
||||
" |* {\n" +
|
||||
" color: rgb(4, 5, 6);\n" +
|
||||
" }\n" +
|
||||
" background-color: rgb(7, 8, 9);\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
".rec-malformed {\n" +
|
||||
" color: rgb(20, 21, 22);\n" +
|
||||
" : {\n" +
|
||||
" color: rgb(23, 24, 25);\n" +
|
||||
" }\n" +
|
||||
" border-top-style: solid;\n" +
|
||||
" border-top-color: rgb(26, 27, 28);\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
".rec-group {\n" +
|
||||
" color: rgb(32, 33, 34);\n" +
|
||||
" @counter-style rec-counter {\n" +
|
||||
" system: fixed;\n" +
|
||||
" symbols: a;\n" +
|
||||
" }\n" +
|
||||
" background-color: rgb(35, 36, 37);\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
".rec-tail {\n" +
|
||||
" color: rgb(50, 51, 52);\n" +
|
||||
"}\n";
|
||||
document.head.appendChild(style);
|
||||
return style;
|
||||
}
|
||||
|
||||
function runChecks(style, report) {
|
||||
var recBase = document.getElementById("recBase");
|
||||
var recBaseChild = document.getElementById("recBaseChild");
|
||||
var recMalformed = document.getElementById("recMalformed");
|
||||
var recGroup = document.getElementById("recGroup");
|
||||
var recTail = document.getElementById("recTail");
|
||||
|
||||
report(propOf(window, recBase, "color") === "rgb(1, 2, 3)",
|
||||
"unsupported nested selector should not wipe earlier declarations",
|
||||
propOf(window, recBase, "color"),
|
||||
"rgb(1, 2, 3)");
|
||||
report(propOf(window, recBase, "background-color") === "rgb(7, 8, 9)",
|
||||
"unsupported nested selector should not wipe later declarations",
|
||||
propOf(window, recBase, "background-color"),
|
||||
"rgb(7, 8, 9)");
|
||||
report(propOf(window, recBaseChild, "color") === "rgb(1, 2, 3)",
|
||||
"unsupported nested selector should not restyle descendants unexpectedly",
|
||||
propOf(window, recBaseChild, "color"),
|
||||
"rgb(1, 2, 3)");
|
||||
|
||||
report(propOf(window, recMalformed, "color") === "rgb(20, 21, 22)",
|
||||
"malformed nested selector should keep declaration before it",
|
||||
propOf(window, recMalformed, "color"),
|
||||
"rgb(20, 21, 22)");
|
||||
report(propOf(window, recMalformed, "border-top-color") === "rgb(26, 27, 28)",
|
||||
"malformed nested selector should keep declaration after it",
|
||||
propOf(window, recMalformed, "border-top-color"),
|
||||
"rgb(26, 27, 28)");
|
||||
|
||||
report(propOf(window, recGroup, "color") === "rgb(32, 33, 34)",
|
||||
"nested unsupported at-rule should keep declaration before it",
|
||||
propOf(window, recGroup, "color"),
|
||||
"rgb(32, 33, 34)");
|
||||
report(propOf(window, recGroup, "background-color") === "rgb(35, 36, 37)",
|
||||
"nested unsupported at-rule should keep declaration after it",
|
||||
propOf(window, recGroup, "background-color"),
|
||||
"rgb(35, 36, 37)");
|
||||
|
||||
report(propOf(window, recTail, "color") === "rgb(50, 51, 52)",
|
||||
"rules after recovery scenarios should still parse",
|
||||
propOf(window, recTail, "color"),
|
||||
"rgb(50, 51, 52)");
|
||||
|
||||
report(style.sheet.cssRules.length >= 4,
|
||||
"stylesheet should remain parseable after recovery scenarios",
|
||||
String(style.sheet.cssRules.length),
|
||||
">= 4");
|
||||
}
|
||||
|
||||
function runStandalone() {
|
||||
var log = document.getElementById("standalone-log");
|
||||
var lines = [
|
||||
"Standalone mode.",
|
||||
"This page only demonstrates nesting if layout.css.nesting.enabled is already true in the browser.",
|
||||
""
|
||||
];
|
||||
var style = appendTestSheet();
|
||||
|
||||
runChecks(style, function(pass, message, actual, expected) {
|
||||
lines.push((pass ? "PASS" : "FAIL") + ": " + message);
|
||||
if (!pass) {
|
||||
lines.push(" expected: " + expected);
|
||||
lines.push(" actual: " + actual);
|
||||
}
|
||||
});
|
||||
|
||||
log.textContent = lines.join("\n");
|
||||
}
|
||||
|
||||
function runMochitest() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({
|
||||
set: [["layout.css.nesting.enabled", true]]
|
||||
}, function() {
|
||||
var style = appendTestSheet();
|
||||
|
||||
runChecks(style, function(pass, message, actual, expected) {
|
||||
ok(pass, message + " (expected: " + expected + ", actual: " + actual + ")");
|
||||
});
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof SimpleTest !== "undefined" && typeof SpecialPowers !== "undefined") {
|
||||
runMochitest();
|
||||
} else {
|
||||
runStandalone();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
* Platform-specific #ifdefs at the end of this file override the generic
|
||||
* entries at the top.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* SYNTAX HINTS:
|
||||
|
|
@ -639,7 +639,7 @@ pref("layout.event-regions.enabled", false);
|
|||
// gfx/layers/apz/src/AsyncPanZoomController.cpp.
|
||||
pref("apz.allow_checkerboarding", true);
|
||||
pref("apz.allow_immediate_handoff", true);
|
||||
pref("apz.allow_zooming", true);
|
||||
pref("apz.allow_zooming", false);
|
||||
|
||||
// Whether to lock touch scrolling to one axis at a time
|
||||
// 0 = FREE (No locking at all)
|
||||
|
|
@ -651,7 +651,7 @@ pref("apz.axis_lock.breakout_threshold", "0.03125"); // 1/32 inches
|
|||
pref("apz.axis_lock.breakout_angle", "0.3926991"); // PI / 8 (22.5 degrees)
|
||||
pref("apz.axis_lock.direct_pan_angle", "1.047197"); // PI / 3 (60 degrees)
|
||||
pref("apz.content_response_timeout", 400);
|
||||
pref("apz.drag.enabled", true);
|
||||
pref("apz.drag.enabled", false);
|
||||
pref("apz.danger_zone_x", 50);
|
||||
pref("apz.danger_zone_y", 100);
|
||||
pref("apz.disable_for_scroll_linked_effects", false);
|
||||
|
|
@ -710,7 +710,7 @@ pref("apz.zoom_animation_duration_ms", 250);
|
|||
pref("apz.scale_repaint_delay_ms", 500);
|
||||
|
||||
#if !defined(MOZ_WIDGET_UIKIT)
|
||||
pref("apz.desktop.enabled", true);
|
||||
pref("apz.desktop.enabled", false);
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
|
@ -1348,9 +1348,6 @@ pref("javascript.options.dynamicImport", true);
|
|||
// Streams API
|
||||
pref("javascript.options.streams", true);
|
||||
|
||||
// Enable garbage collection of weakrefed objects
|
||||
pref("javascript.options.weakrefs", false);
|
||||
|
||||
// advanced prefs
|
||||
pref("advanced.mailftp", false);
|
||||
pref("image.animation_mode", "normal");
|
||||
|
|
@ -2728,9 +2725,6 @@ pref("layout.css.resizeobserver.enabled", true);
|
|||
// Is support for cascade layers enabled?
|
||||
pref("layout.css.cascade-layers.enabled", true);
|
||||
|
||||
// Is support for basic CSS nesting lowering enabled?
|
||||
pref("layout.css.nesting.enabled", true);
|
||||
|
||||
// Should rules in imported style sheets be added based on the order
|
||||
// of appearance of their respective @import rules in the parent
|
||||
// style sheet? Otherwise, they are added before rules preceding
|
||||
|
|
@ -3236,7 +3230,7 @@ pref("ui.mouse.radius.inputSource.touchOnly", true);
|
|||
|
||||
#ifdef XP_WIN
|
||||
|
||||
// Be as uniform as possible, use Twemoji everywhere.
|
||||
// Be as uniform as possible, use Twemoji everywhere.
|
||||
// Optional: prefix with `Segoe UI Emoji` to use Win8+ Segoe UI font emoji where available.
|
||||
pref("font.name-list.emoji", "Twemoji Mozilla");
|
||||
|
||||
|
|
@ -4767,7 +4761,7 @@ pref("media.ondevicechange.fakeDeviceChangeEvent.enabled", false);
|
|||
// those platforms we don't handle touch events anyway so it's conceptually
|
||||
// a no-op.
|
||||
pref("layout.css.touch_action.enabled", true);
|
||||
|
||||
|
||||
// WHATWG computed intrinsic aspect ratio for an img element
|
||||
// https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images
|
||||
// Are the width and height attributes on image-like elements mapped to the
|
||||
|
|
@ -5279,7 +5273,7 @@ pref("plugins.navigator_hide_disabled_flash", false);
|
|||
pref("dom.mozBrowserFramesEnabled", false);
|
||||
|
||||
// Thick caret when behind CJK characters
|
||||
pref("layout.cjkthickcaret", true);
|
||||
pref("layout.cjkthickcaret", true);
|
||||
|
||||
// Is support for 'color-adjust' CSS property enabled?
|
||||
pref("layout.css.color-adjust.enabled", true);
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
FINAL_TARGET_FILES.fonts += ['TwemojiMozilla.ttf']
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
|
||||
FINAL_TARGET_FILES.fonts += ['TwemojiMozilla.ttf']
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
Dactyloidae Milsko Toolkit (WIP)
|
||||
|
||||
This is a modified version of Milsko 1.4 (latest release as of 28/7/26, DD/MM/YY),
|
||||
adapted for use on you know, a web browser.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
---
|
||||
UseTab: Always
|
||||
TabWidth: 8
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: true
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: true
|
||||
AccessModifierOffset: -4
|
||||
NamespaceIndentation: All
|
||||
IndentWidth: 8
|
||||
PointerAlignment: Left
|
||||
ColumnLimit: 0
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
SpaceBeforeParens: Never
|
||||
AlignEscapedNewlines: DontAlign
|
||||
SortIncludes: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
#IndentPPDirectives: AfterHash
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
Completion:
|
||||
HeaderInsertion: Never
|
||||
ClangFormat: Tab
|
||||
17
widget/milsko/milskosrc/.gitattributes
vendored
17
widget/milsko/milskosrc/.gitattributes
vendored
|
|
@ -1,17 +0,0 @@
|
|||
/external/*.h linguist-generated
|
||||
/external/*.c linguist-generated
|
||||
/external/libjpeg/include/*.h linguist-generated
|
||||
/external/libjpeg/src/*.c linguist-generated
|
||||
/external/libjpeg/src/*.h linguist-generated
|
||||
/external/libz/include/*.h linguist-generated
|
||||
/external/libz/src/*.c linguist-generated
|
||||
/external/libz/src/*.h linguist-generated
|
||||
/external/libpng/include/*.h linguist-generated
|
||||
/external/libpng/src/*.c linguist-generated
|
||||
/external/libpng/src/*.h linguist-generated
|
||||
/resource/doxygen-theme/* linguist-generated
|
||||
/src/icon/*.c linguist-generated
|
||||
/src/font/*.c linguist-generated
|
||||
/BorMakefile linguist-generated
|
||||
/WatMakefile linguist-generated
|
||||
/NTMakefile linguist-generated
|
||||
33
widget/milsko/milskosrc/.gitignore
vendored
33
widget/milsko/milskosrc/.gitignore
vendored
|
|
@ -1,33 +0,0 @@
|
|||
examples/*
|
||||
examples/*.exe
|
||||
examples/*/*
|
||||
examples/*/*.exe
|
||||
!examples/*/
|
||||
!examples/*.*
|
||||
!examples/*/*.*
|
||||
*.exe
|
||||
*.o
|
||||
*.obj
|
||||
*.core
|
||||
*.so
|
||||
*.dll
|
||||
*.lib
|
||||
*.dylib
|
||||
*.a
|
||||
/Makefile
|
||||
/build
|
||||
compile_flags.txt
|
||||
.cache
|
||||
.DS_Store
|
||||
/vms
|
||||
/BorMakefile
|
||||
*.err
|
||||
*.zip
|
||||
|
||||
*.pef
|
||||
*.dsk
|
||||
*.bin
|
||||
*.rsrc
|
||||
*.finf
|
||||
*.gdb
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
========================= 1.4 =========================
|
||||
- CMakeLists.txt downgraded to version 3.13 to allow compiling on Windows XP
|
||||
- CMake build now generates a pkgconfig file.
|
||||
- GDI backend now natively uses GDI for text rendering
|
||||
- Widgets can now be disabled with MwNdisabled
|
||||
- Added `MwTabFocus` for letting a tab widget steal focus.
|
||||
- New table widget (`MwTableClass`).
|
||||
- Added `MwWindowShouldClose` for letting custom loops know when a window should close.
|
||||
- Remove VMS build files
|
||||
- Entry widgets now have blinking cursor that appears only when you hover over the widget.
|
||||
- Wayland backend:
|
||||
- Can now create layer surfaces (Use `MwLLMakeToolWindow` on a parentless window)
|
||||
- Now properly handles keys being held down
|
||||
- has drastically improved CSD (functionality wise)
|
||||
- Uses KMSDRM directly for the OpenGL widget instead of wl_egl for a smoother experience
|
||||
- Various overall performance improvements putting it on the same level as the X11 backend finally
|
||||
- Menu widget works better under compositors that use CSD.
|
||||
|
|
@ -1,508 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
project(
|
||||
milsko
|
||||
)
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}")
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
endif()
|
||||
|
||||
option(MW_CLASSIC_THEME "Use classic theme" OFF)
|
||||
option(MW_BUILD_EXAMPLES "Build examples" OFF)
|
||||
option(MW_USE_STB_IMAGE "Use stb_image" ON)
|
||||
option(MW_USE_STB_TRUETYPE "Use stb_truetype" OFF)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES Retro)
|
||||
option(MW_BUILD_SHARED "Build a shared library" OFF)
|
||||
option(MW_BUILD_STATIC "Build a static library" ON)
|
||||
option(MW_TRY_OPENGL "Try to compile OpenGL widget or not" OFF)
|
||||
option(MW_TRY_VULKAN "Try to compile Vulkan widget or not" OFF)
|
||||
else()
|
||||
option(MW_BUILD_SHARED "Build a shared library" ON)
|
||||
option(MW_BUILD_STATIC "Build a static library" OFF)
|
||||
option(MW_TRY_OPENGL "Try to compile OpenGL widget or not" ON)
|
||||
option(MW_TRY_VULKAN "Try to compile Vulkan widget or not" ON)
|
||||
endif()
|
||||
|
||||
option(MW_INSTALL_HEADERS "Install headers" ON)
|
||||
|
||||
if( ${CMAKE_SYSTEM_NAME} STREQUAL Darwin
|
||||
OR ${CMAKE_SYSTEM_NAME} MATCHES Retro
|
||||
OR ${CMAKE_SYSTEM_NAME} MATCHES Windows)
|
||||
option(MW_USE_FREETYPE2 "Use FreeType 2" OFF)
|
||||
else()
|
||||
option(MW_USE_FREETYPE2 "Use FreeType 2" ON)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL Windows)
|
||||
option(MW_USE_GDI_TEXT "Use GDI for text rendering" ON)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL Linux OR ${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD)
|
||||
option(MW_USE_WAYLAND "Enable Wayland backend" ON)
|
||||
endif()
|
||||
|
||||
file(
|
||||
GLOB
|
||||
SOURCES
|
||||
external/libz/src/*.c src/*.c src/cursor/*.c src/icon/*.c src/widget/*.c src/text/*.c src/text/font/*.c src/dialog/*.c src/abstract/*.c external/*.c
|
||||
)
|
||||
|
||||
if(NOT MW_USE_STB_IMAGE)
|
||||
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_image.c")
|
||||
endif()
|
||||
|
||||
if(NOT MW_USE_STB_TRUETYPE)
|
||||
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_truetype.c")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/X11R7/include")
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/pkg/include")
|
||||
endif()
|
||||
|
||||
if(MW_TRY_OPENGL)
|
||||
find_package(OpenGL)
|
||||
if(OpenGL_FOUND AND NOT APPLE)
|
||||
set(MW_BUILD_OPENGL ON)
|
||||
message(STATUS "OpenGL widget has been enabled")
|
||||
else()
|
||||
message(WARNING "OpenGL widget has been disabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MW_TRY_VULKAN)
|
||||
find_package(Vulkan)
|
||||
if(${Vulkan_FOUND})
|
||||
set(MW_BUILD_VULKAN ON)
|
||||
message(STATUS "Vulkan widget has been enabled")
|
||||
else()
|
||||
message(WARNING "Vulkan widget has been disabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MW_BUILD_STATIC)
|
||||
message(STATUS "Building Milsko as a static library")
|
||||
add_library(
|
||||
Mw
|
||||
${SOURCES}
|
||||
)
|
||||
elseif(MW_BUILD_SHARED)
|
||||
message(STATUS "Building Milsko as a shared library")
|
||||
add_library(
|
||||
Mw
|
||||
SHARED
|
||||
${SOURCES}
|
||||
)
|
||||
else()
|
||||
message(ERROR "Must either build a shared library or a static library")
|
||||
endif()
|
||||
|
||||
if(MW_USE_STB_IMAGE)
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_STB_IMAGE
|
||||
)
|
||||
else()
|
||||
file(
|
||||
GLOB
|
||||
IMAGE_SOURCES
|
||||
external/libjpeg/src/*.c external/libpng/src/*.c
|
||||
)
|
||||
target_sources(
|
||||
Mw
|
||||
PRIVATE
|
||||
${MW_IMAGE_SOURCES}
|
||||
)
|
||||
target_include_directories(
|
||||
Mw
|
||||
PRIVATE
|
||||
external/libjpeg/include external/libpng/include
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MW_USE_STB_TRUETYPE)
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_STB_TRUETYPE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MW_USE_FREETYPE2)
|
||||
find_package(Freetype)
|
||||
if(Freetype_FOUND)
|
||||
message(STATUS "FreeType2 found")
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_FREETYPE2
|
||||
)
|
||||
|
||||
list(APPEND INCLUDE_DIRS ${FREETYPE_INCLUDE_DIRS})
|
||||
list(APPEND LIBRARY_DIRS ${FREETYPE_LIBRARY_DIRS})
|
||||
else()
|
||||
message(WARNING "FreeType2 not found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
if(MW_USE_GDI_TEXT)
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_GDI_TEXT
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MW_USE_WAYLAND)
|
||||
function(scan_wayland_protocol_core)
|
||||
execute_process(
|
||||
COMMAND wayland-scanner private-code /usr/share/wayland/wayland.xml ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland/wayland-core-protocol.c
|
||||
OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT
|
||||
ERROR_VARIABLE WAYLAND_SCANNER_ERROR
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
ECHO_ERROR_VARIABLE
|
||||
COMMAND_ECHO STDOUT
|
||||
)
|
||||
target_sources(
|
||||
Mw
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland/wayland-core-protocol.c
|
||||
)
|
||||
execute_process(
|
||||
COMMAND wayland-scanner client-header /usr/share/wayland/wayland.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/wayland-core-protocol.h
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT
|
||||
ERROR_VARIABLE WAYLAND_SCANNER_ERROR
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
ECHO_ERROR_VARIABLE
|
||||
COMMAND_ECHO STDOUT
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(scan_wayland_protocol tier proto ver)
|
||||
SET(proto_c ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland/wayland-${proto}-protocol.c)
|
||||
execute_process(
|
||||
COMMAND wayland-scanner private-code /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${proto_c}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT
|
||||
ERROR_VARIABLE WAYLAND_SCANNER_ERROR
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
ECHO_ERROR_VARIABLE
|
||||
COMMAND_ECHO STDOUT
|
||||
)
|
||||
target_sources(
|
||||
Mw
|
||||
PRIVATE
|
||||
${proto_c}
|
||||
)
|
||||
execute_process(
|
||||
COMMAND wayland-scanner client-header /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/${proto}-client-protocol.h
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT
|
||||
ERROR_VARIABLE WAYLAND_SCANNER_ERROR
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
ECHO_ERROR_VARIABLE
|
||||
COMMAND_ECHO STDOUT
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(scan_wayland_protocol_from_file proto file)
|
||||
SET(proto_c ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland/wayland-${proto}-protocol.c)
|
||||
execute_process(
|
||||
COMMAND wayland-scanner private-code ${CMAKE_CURRENT_SOURCE_DIR}/resource/wayland/${file} ${proto_c}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT
|
||||
ERROR_VARIABLE WAYLAND_SCANNER_ERROR
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
ECHO_ERROR_VARIABLE
|
||||
COMMAND_ECHO STDOUT
|
||||
)
|
||||
target_sources(
|
||||
Mw
|
||||
PRIVATE
|
||||
${proto_c}
|
||||
)
|
||||
execute_process(
|
||||
COMMAND wayland-scanner client-header ${CMAKE_CURRENT_SOURCE_DIR}/resource/wayland/${file} ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/${proto}-client-protocol.h
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT
|
||||
ERROR_VARIABLE WAYLAND_SCANNER_ERROR
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
ECHO_ERROR_VARIABLE
|
||||
COMMAND_ECHO STDOUT
|
||||
)
|
||||
endfunction()
|
||||
|
||||
check_include_files(wayland-client.h HAVE_WL_H)
|
||||
check_include_files(xkbcommon/xkbcommon.h HAVE_XKBCOMMON_H)
|
||||
check_include_files(cairo/cairo.h HAVE_CAIRO_H)
|
||||
if(HAVE_WL_H)
|
||||
if(HAVE_XKBCOMMON_H)
|
||||
if(HAVE_CAIRO_H)
|
||||
scan_wayland_protocol_core()
|
||||
scan_wayland_protocol("stable" "xdg-shell" "")
|
||||
scan_wayland_protocol("stable" "viewporter" "")
|
||||
scan_wayland_protocol("stable" "tablet" "-v2")
|
||||
scan_wayland_protocol("staging" "xdg-toplevel-icon" "-v1")
|
||||
scan_wayland_protocol("staging" "cursor-shape" "-v1")
|
||||
scan_wayland_protocol("unstable" "xdg-decoration" "-unstable-v1")
|
||||
scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1")
|
||||
scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1")
|
||||
scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1")
|
||||
scan_wayland_protocol_from_file("wlr-layer-shell" "wlr-layer-shell-unstable-v1.xml")
|
||||
|
||||
target_sources(
|
||||
Mw
|
||||
PRIVATE
|
||||
src/backend/cairo.c
|
||||
src/backend/wayland/wayland.c
|
||||
src/backend/wayland/buffer.c
|
||||
src/backend/wayland/interfaces.c
|
||||
src/backend/wayland/region.c
|
||||
)
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_WAYLAND
|
||||
)
|
||||
message(STATUS "Wayland backend has been enabled")
|
||||
else()
|
||||
message(WARNING "Wayland backend has been disabled")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Wayland backend has been disabled")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Wayland backend has been disabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE AND MW_BUILD_OPENGL)
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
GL_SILENCE_DEPRECATION
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
Mw
|
||||
PRIVATE
|
||||
external/libz/include
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
Mw
|
||||
PUBLIC
|
||||
include
|
||||
)
|
||||
|
||||
if(MW_CLASSIC_THEME)
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_CLASSIC_THEME
|
||||
)
|
||||
endif()
|
||||
|
||||
message("Building Milsko for ${CMAKE_SYSTEM_NAME}")
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_SYSTEM_NAME STREQUAL "MSYS")
|
||||
target_sources(
|
||||
Mw
|
||||
PRIVATE
|
||||
src/backend/gdi.c
|
||||
)
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_GDI
|
||||
)
|
||||
list(APPEND LIBRARIES gdi32 winmm)
|
||||
target_link_options(
|
||||
Mw
|
||||
PRIVATE
|
||||
-static-libgcc
|
||||
)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
# target_sources(
|
||||
# Mw
|
||||
# PRIVATE
|
||||
# src/backend/cocoa.m
|
||||
# )
|
||||
target_sources(
|
||||
Mw
|
||||
PRIVATE
|
||||
src/backend/nococoa.m
|
||||
)
|
||||
# target_compile_definitions(
|
||||
# Mw
|
||||
# PRIVATE
|
||||
# USE_COCOA
|
||||
# )
|
||||
list(APPEND LIBRARIES objc)
|
||||
target_link_options(
|
||||
Mw
|
||||
PRIVATE
|
||||
-framework Cocoa
|
||||
)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Retro")
|
||||
|
||||
target_sources(
|
||||
Mw
|
||||
PRIVATE
|
||||
src/backend/classicmacos.c
|
||||
)
|
||||
if(PLATFORM MATCHES retroppc)
|
||||
set_target_properties(Mw PROPERTIES COMPILE_FLAGS "-ffunction-sections -mcpu=601 -Os -Wall -Wextra -Wno-unused-parameter")
|
||||
set_target_properties(Mw PROPERTIES LINK_FLAGS "-Wl,-gc-sections")
|
||||
endif()
|
||||
|
||||
list(APPEND LIBRARIES InterfaceLib WindowsLib ThreadsLib)
|
||||
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
CLASSIC_MAC_OS
|
||||
)
|
||||
else()
|
||||
|
||||
find_package(PkgConfig)
|
||||
find_package(X11)
|
||||
pkg_check_modules(DBUS dbus-1)
|
||||
|
||||
target_sources(
|
||||
Mw
|
||||
PRIVATE
|
||||
src/backend/x11.c
|
||||
)
|
||||
|
||||
if(${X11_FOUND})
|
||||
list(APPEND INCLUDE_DIRS ${X11_INCLUDE_DIRS})
|
||||
list(APPEND LIBRARY_DIRS ${X11_LIBRARY_DIRS})
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_X11
|
||||
)
|
||||
endif()
|
||||
if(${X11_Xrender_FOUND})
|
||||
list(APPEND INCLUDE_DIRS ${XRENDER_INCLUDE_DIRS})
|
||||
list(APPEND LIBRARY_DIRS ${XRENDER_LIBRARY_DIRS})
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_XRENDER
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
list(APPEND LIBRARIES dl)
|
||||
endif()
|
||||
|
||||
find_package(DBus1)
|
||||
|
||||
if(${DBus1_FOUND})
|
||||
list(APPEND INCLUDE_DIRS ${DBUS_INCLUDE_DIRS})
|
||||
list(APPEND LIBRARY_DIRS ${DBUS_LIBRARY_DIRS})
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
USE_DBUS
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
if(UNIX)
|
||||
list(APPEND LIBRARIES m)
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
Mw
|
||||
PRIVATE
|
||||
${INCLUDE_DIRS}
|
||||
)
|
||||
target_link_directories(
|
||||
Mw
|
||||
PRIVATE
|
||||
${LIBRARY_DIRS}
|
||||
)
|
||||
target_link_libraries(
|
||||
Mw
|
||||
PRIVATE
|
||||
${LIBRARIES}
|
||||
)
|
||||
|
||||
if(MW_BUILD_OPENGL)
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
MW_OPENGL
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MW_BUILD_VULKAN)
|
||||
check_include_files(vulkan/vk_enum_string_helper.h HAS_VK_ENUM_STRING_HELPER)
|
||||
if(HAS_VK_ENUM_STRING_HELPER)
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
HAS_VK_ENUM_STRING_HELPER
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
MW_VULKAN
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(
|
||||
Mw
|
||||
PRIVATE
|
||||
_MILSKO _MILSKO_BUILD
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS Mw
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/resource/${PROJECT_NAME}.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
|
||||
@ONLY
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
|
||||
DESTINATION $ENV{MINGW_PREFIX}/${CMAKE_INSTALL_DATADIR}/pkgconfig
|
||||
)
|
||||
|
||||
if(MW_INSTALL_HEADERS)
|
||||
install(
|
||||
DIRECTORY include/
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING PATTERN "*.h"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MW_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
PROJECT_LOGO = resource/logo/logo64.png
|
||||
PROJECT_NAME = Milsko
|
||||
PROJECT_BRIEF = "Lightweight and fast GUI toolkit"
|
||||
OUTPUT_DIRECTORY = doxygen
|
||||
TAB_SIZE = 8
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
MARKDOWN_SUPPORT = YES
|
||||
FILE_PATTERNS = *.h *.md
|
||||
INPUT = include/Mw
|
||||
INPUT += doc
|
||||
RECURSIVE = YES
|
||||
SOURCE_BROWSER = YES
|
||||
HTML_DYNAMIC_MENUS = YES
|
||||
GENERATE_TREEVIEW = YES
|
||||
FULL_SIDEBAR = NO
|
||||
DISABLE_INDEX = NO
|
||||
HAVE_DOT = YES
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH = include/ doc/
|
||||
ENABLED_SECTIONS = YES
|
||||
OUTPUT_LANGUAGE = English
|
||||
GENERATE_LATEX = NO
|
||||
EXTRACT_ALL = YES
|
||||
|
||||
HTML_EXTRA_STYLESHEET = resource/doxygen-theme/doxygen-awesome.css
|
||||
HTML_COLORSTYLE = LIGHT
|
||||
105
widget/milsko/milskosrc/Jenkinsfile
vendored
105
widget/milsko/milskosrc/Jenkinsfile
vendored
|
|
@ -1,105 +0,0 @@
|
|||
pipeline {
|
||||
agent {
|
||||
label "built-in"
|
||||
}
|
||||
stages {
|
||||
stage("Build document") {
|
||||
when {
|
||||
branch "master"
|
||||
}
|
||||
agent {
|
||||
label "built-in"
|
||||
}
|
||||
steps {
|
||||
sh("rm -rf include/Mw/LowLevel/Wayland")
|
||||
sh("doxygen")
|
||||
sh("rm -rf /var/www/milsko-doxygen")
|
||||
sh("mv doxygen/html /var/www/milsko-doxygen")
|
||||
}
|
||||
post {
|
||||
always {
|
||||
notifyDiscord()
|
||||
}
|
||||
}
|
||||
}
|
||||
stage("Build") {
|
||||
parallel {
|
||||
stage("Build for Linux 64-bit") {
|
||||
agent {
|
||||
label "built-in"
|
||||
}
|
||||
steps {
|
||||
sh("git clean -dfx")
|
||||
sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper")
|
||||
sh("make -j4")
|
||||
sh("mv src/libMw.so libMw64.so")
|
||||
archiveArtifacts("libMw64.so")
|
||||
}
|
||||
}
|
||||
stage("Build for Windows 32-bit") {
|
||||
agent {
|
||||
label "built-in"
|
||||
}
|
||||
steps {
|
||||
sh("git clean -dfx")
|
||||
sh("./configure --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=i686-w64-mingw32")
|
||||
sh("make -j4")
|
||||
sh("mv src/Mw.dll Mw32.dll")
|
||||
sh("mv src/libMw.dll.a libMw32.dll.a")
|
||||
archiveArtifacts("Mw32.dll,libMw32.dll.a")
|
||||
}
|
||||
}
|
||||
stage("Build for Windows 64-bit") {
|
||||
agent {
|
||||
label "built-in"
|
||||
}
|
||||
steps {
|
||||
sh("git clean -dfx")
|
||||
sh("./configure --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=x86_64-w64-mingw32")
|
||||
sh("make -j4")
|
||||
sh("mv src/Mw.dll Mw64.dll")
|
||||
sh("mv src/libMw.dll.a libMw64.dll.a")
|
||||
archiveArtifacts("Mw64.dll,libMw64.dll.a")
|
||||
}
|
||||
}
|
||||
stage("Build for Windows 32-bit (MSVC)") {
|
||||
agent {
|
||||
label "2012r2"
|
||||
}
|
||||
steps {
|
||||
bat("git clean -dfx")
|
||||
bat("nmake -f NTMakefile")
|
||||
bat("move /y src\\Mw.dll MwMSVC32.dll")
|
||||
bat("move /y src\\Mw.lib MwMSVC32.lib")
|
||||
archiveArtifacts("MwMSVC32.dll,MwMSVC32.lib")
|
||||
}
|
||||
}
|
||||
stage("Build for Windows 32-bit (Watcom)") {
|
||||
agent {
|
||||
label "built-in"
|
||||
}
|
||||
environment {
|
||||
WATCOM = "/usr/watcom"
|
||||
INCLUDE = "/usr/watcom/h:/usr/watcom/h/nt"
|
||||
PATH = "/usr/watcom/binl64:${env.PATH}"
|
||||
}
|
||||
steps {
|
||||
sh("git clean -dfx")
|
||||
sh("wmake -f WatMakefile")
|
||||
sh("mv src/Mw.dll MwWat32.dll")
|
||||
sh("mv src/Mw.lib MwWat32.lib")
|
||||
archiveArtifacts("MwWat32.dll,MwWat32.lib")
|
||||
sh("./tools/watcom-pack.sh")
|
||||
sh("mv milsko-examples.zip milsko-examples-win32.zip")
|
||||
archiveArtifacts("milsko-examples-win32.zip")
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
notifyDiscord()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
Copyright (c) 2025-2026, Pyrite development team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the <organization> nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -1,328 +0,0 @@
|
|||
CC = cl /TC /c /nologo
|
||||
LD = link /nologo
|
||||
|
||||
MW_CFLAGS = /Iinclude /Iexternal\libz\include /D_MILSKO /D_MILSKO_BUILD /DUSE_GDI /DUSE_STB_IMAGE /DSTBI_NO_SIMD /DUSE_GDI_TEXT
|
||||
MW_LDFLAGS = /DLL
|
||||
EXE_CFLAGS = /Iinclude
|
||||
EXE_LDFLAGS =
|
||||
.SUFFIXES: .obj .c
|
||||
all: src\Mw.dll examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe
|
||||
lib: src\Mw.dll
|
||||
examples: examples\basic\box.exe examples\basic\calculator.exe examples\basic\checkbox.exe examples\basic\clipboard.exe examples\basic\colorpicker.exe examples\basic\combobox.exe examples\basic\example.exe examples\basic\filechooser.exe examples\basic\image.exe examples\basic\listbox.exe examples\basic\messagebox.exe examples\basic\periodic.exe examples\basic\progressbar.exe examples\basic\radiobox.exe examples\basic\rotate.exe examples\basic\scrollbar.exe examples\basic\sevensegment.exe examples\basic\subwindow.exe examples\basic\tab.exe examples\basic\treeview.exe examples\basic\viewport.exe examples\gldemos\boing.exe examples\gldemos\clock.exe examples\gldemos\cube.exe examples\gldemos\gears.exe examples\gldemos\triangle.exe examples\gldemos\tripaint.exe
|
||||
clean:
|
||||
del /f /q external\libz\src\adler32.obj
|
||||
del /f /q external\libz\src\compress.obj
|
||||
del /f /q external\libz\src\crc32.obj
|
||||
del /f /q external\libz\src\deflate.obj
|
||||
del /f /q external\libz\src\gzclose.obj
|
||||
del /f /q external\libz\src\gzlib.obj
|
||||
del /f /q external\libz\src\gzread.obj
|
||||
del /f /q external\libz\src\gzwrite.obj
|
||||
del /f /q external\libz\src\infback.obj
|
||||
del /f /q external\libz\src\inffast.obj
|
||||
del /f /q external\libz\src\inflate.obj
|
||||
del /f /q external\libz\src\inftrees.obj
|
||||
del /f /q external\libz\src\trees.obj
|
||||
del /f /q external\libz\src\uncompr.obj
|
||||
del /f /q external\libz\src\zutil.obj
|
||||
del /f /q external\stb_ds.obj
|
||||
del /f /q external\stb_image.obj
|
||||
del /f /q external\stb_truetype.obj
|
||||
del /f /q src\abstract\charset.obj
|
||||
del /f /q src\abstract\directory.obj
|
||||
del /f /q src\abstract\dynamic.obj
|
||||
del /f /q src\abstract\time.obj
|
||||
del /f /q src\backend\gdi.obj
|
||||
del /f /q src\color.obj
|
||||
del /f /q src\core.obj
|
||||
del /f /q src\cursor\arrow.obj
|
||||
del /f /q src\cursor\cross.obj
|
||||
del /f /q src\cursor\default.obj
|
||||
del /f /q src\cursor\hidden.obj
|
||||
del /f /q src\cursor\text.obj
|
||||
del /f /q src\default.obj
|
||||
del /f /q src\dialog\colorpicker.obj
|
||||
del /f /q src\dialog\directorychooser.obj
|
||||
del /f /q src\dialog\filechooser.obj
|
||||
del /f /q src\dialog\messagebox.obj
|
||||
del /f /q src\draw.obj
|
||||
del /f /q src\icon\back.obj
|
||||
del /f /q src\icon\clock.obj
|
||||
del /f /q src\icon\computer.obj
|
||||
del /f /q src\icon\directory.obj
|
||||
del /f /q src\icon\down.obj
|
||||
del /f /q src\icon\error.obj
|
||||
del /f /q src\icon\file.obj
|
||||
del /f /q src\icon\forward.obj
|
||||
del /f /q src\icon\info.obj
|
||||
del /f /q src\icon\left.obj
|
||||
del /f /q src\icon\news.obj
|
||||
del /f /q src\icon\note.obj
|
||||
del /f /q src\icon\right.obj
|
||||
del /f /q src\icon\search.obj
|
||||
del /f /q src\icon\up.obj
|
||||
del /f /q src\icon\warning.obj
|
||||
del /f /q src\lowlevel.obj
|
||||
del /f /q src\string.obj
|
||||
del /f /q src\text\font\boldfont.obj
|
||||
del /f /q src\text\font\boldmonottf.obj
|
||||
del /f /q src\text\font\boldttf.obj
|
||||
del /f /q src\text\font\font.obj
|
||||
del /f /q src\text\font\monottf.obj
|
||||
del /f /q src\text\font\ttf.obj
|
||||
del /f /q src\text\ft2.obj
|
||||
del /f /q src\text\gdi.obj
|
||||
del /f /q src\text\stbtt.obj
|
||||
del /f /q src\text\text.obj
|
||||
del /f /q src\truetype.obj
|
||||
del /f /q src\unicode.obj
|
||||
del /f /q src\widget\box.obj
|
||||
del /f /q src\widget\button.obj
|
||||
del /f /q src\widget\calendar.obj
|
||||
del /f /q src\widget\checkbox.obj
|
||||
del /f /q src\widget\combobox.obj
|
||||
del /f /q src\widget\entry.obj
|
||||
del /f /q src\widget\frame.obj
|
||||
del /f /q src\widget\image.obj
|
||||
del /f /q src\widget\label.obj
|
||||
del /f /q src\widget\listbox.obj
|
||||
del /f /q src\widget\menu.obj
|
||||
del /f /q src\widget\numberentry.obj
|
||||
del /f /q src\widget\opengl.obj
|
||||
del /f /q src\widget\progressbar.obj
|
||||
del /f /q src\widget\radiobox.obj
|
||||
del /f /q src\widget\scrollbar.obj
|
||||
del /f /q src\widget\separator.obj
|
||||
del /f /q src\widget\submenu.obj
|
||||
del /f /q src\widget\subwindow.obj
|
||||
del /f /q src\widget\tab.obj
|
||||
del /f /q src\widget\table.obj
|
||||
del /f /q src\widget\treeview.obj
|
||||
del /f /q src\widget\viewport.obj
|
||||
del /f /q src\widget\window.obj
|
||||
del /f /q src\Mw.dll
|
||||
del /f /q src\Mw.lib
|
||||
del /f /q examples\basic\box.obj
|
||||
del /f /q examples\basic\calculator.obj
|
||||
del /f /q examples\basic\checkbox.obj
|
||||
del /f /q examples\basic\clipboard.obj
|
||||
del /f /q examples\basic\colorpicker.obj
|
||||
del /f /q examples\basic\combobox.obj
|
||||
del /f /q examples\basic\example.obj
|
||||
del /f /q examples\basic\filechooser.obj
|
||||
del /f /q examples\basic\image.obj
|
||||
del /f /q examples\basic\listbox.obj
|
||||
del /f /q examples\basic\messagebox.obj
|
||||
del /f /q examples\basic\periodic.obj
|
||||
del /f /q examples\basic\progressbar.obj
|
||||
del /f /q examples\basic\radiobox.obj
|
||||
del /f /q examples\basic\rotate.obj
|
||||
del /f /q examples\basic\scrollbar.obj
|
||||
del /f /q examples\basic\sevensegment.obj
|
||||
del /f /q examples\basic\subwindow.obj
|
||||
del /f /q examples\basic\tab.obj
|
||||
del /f /q examples\basic\treeview.obj
|
||||
del /f /q examples\basic\viewport.obj
|
||||
del /f /q examples\gldemos\boing.obj
|
||||
del /f /q examples\gldemos\clock.obj
|
||||
del /f /q examples\gldemos\cube.obj
|
||||
del /f /q examples\gldemos\gears.obj
|
||||
del /f /q examples\gldemos\triangle.obj
|
||||
del /f /q examples\gldemos\tripaint.obj
|
||||
del /f /q examples\basic\box.exe
|
||||
del /f /q examples\basic\calculator.exe
|
||||
del /f /q examples\basic\checkbox.exe
|
||||
del /f /q examples\basic\clipboard.exe
|
||||
del /f /q examples\basic\colorpicker.exe
|
||||
del /f /q examples\basic\combobox.exe
|
||||
del /f /q examples\basic\example.exe
|
||||
del /f /q examples\basic\filechooser.exe
|
||||
del /f /q examples\basic\image.exe
|
||||
del /f /q examples\basic\listbox.exe
|
||||
del /f /q examples\basic\messagebox.exe
|
||||
del /f /q examples\basic\periodic.exe
|
||||
del /f /q examples\basic\progressbar.exe
|
||||
del /f /q examples\basic\radiobox.exe
|
||||
del /f /q examples\basic\rotate.exe
|
||||
del /f /q examples\basic\scrollbar.exe
|
||||
del /f /q examples\basic\sevensegment.exe
|
||||
del /f /q examples\basic\subwindow.exe
|
||||
del /f /q examples\basic\tab.exe
|
||||
del /f /q examples\basic\treeview.exe
|
||||
del /f /q examples\basic\viewport.exe
|
||||
del /f /q examples\gldemos\boing.exe
|
||||
del /f /q examples\gldemos\clock.exe
|
||||
del /f /q examples\gldemos\cube.exe
|
||||
del /f /q examples\gldemos\gears.exe
|
||||
del /f /q examples\gldemos\triangle.exe
|
||||
del /f /q examples\gldemos\tripaint.exe
|
||||
|
||||
examples\basic\box.exe: examples\basic\box.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\box.obj src\Mw.lib
|
||||
|
||||
examples\basic\box.obj: examples/basic/box.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/box.c
|
||||
|
||||
examples\basic\calculator.exe: examples\basic\calculator.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\calculator.obj src\Mw.lib
|
||||
|
||||
examples\basic\calculator.obj: examples/basic/calculator.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/calculator.c
|
||||
|
||||
examples\basic\checkbox.exe: examples\basic\checkbox.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\checkbox.obj src\Mw.lib
|
||||
|
||||
examples\basic\checkbox.obj: examples/basic/checkbox.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/checkbox.c
|
||||
|
||||
examples\basic\clipboard.exe: examples\basic\clipboard.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\clipboard.obj src\Mw.lib
|
||||
|
||||
examples\basic\clipboard.obj: examples/basic/clipboard.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/clipboard.c
|
||||
|
||||
examples\basic\colorpicker.exe: examples\basic\colorpicker.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\colorpicker.obj src\Mw.lib
|
||||
|
||||
examples\basic\colorpicker.obj: examples/basic/colorpicker.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/colorpicker.c
|
||||
|
||||
examples\basic\combobox.exe: examples\basic\combobox.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\combobox.obj src\Mw.lib
|
||||
|
||||
examples\basic\combobox.obj: examples/basic/combobox.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/combobox.c
|
||||
|
||||
examples\basic\example.exe: examples\basic\example.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\example.obj src\Mw.lib
|
||||
|
||||
examples\basic\example.obj: examples/basic/example.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/example.c
|
||||
|
||||
examples\basic\filechooser.exe: examples\basic\filechooser.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\filechooser.obj src\Mw.lib
|
||||
|
||||
examples\basic\filechooser.obj: examples/basic/filechooser.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/filechooser.c
|
||||
|
||||
examples\basic\image.exe: examples\basic\image.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\image.obj src\Mw.lib
|
||||
|
||||
examples\basic\image.obj: examples/basic/image.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/image.c
|
||||
|
||||
examples\basic\listbox.exe: examples\basic\listbox.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\listbox.obj src\Mw.lib
|
||||
|
||||
examples\basic\listbox.obj: examples/basic/listbox.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/listbox.c
|
||||
|
||||
examples\basic\messagebox.exe: examples\basic\messagebox.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\messagebox.obj src\Mw.lib
|
||||
|
||||
examples\basic\messagebox.obj: examples/basic/messagebox.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/messagebox.c
|
||||
|
||||
examples\basic\periodic.exe: examples\basic\periodic.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\periodic.obj src\Mw.lib
|
||||
|
||||
examples\basic\periodic.obj: examples/basic/periodic.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/periodic.c
|
||||
|
||||
examples\basic\progressbar.exe: examples\basic\progressbar.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\progressbar.obj src\Mw.lib
|
||||
|
||||
examples\basic\progressbar.obj: examples/basic/progressbar.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/progressbar.c
|
||||
|
||||
examples\basic\radiobox.exe: examples\basic\radiobox.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\radiobox.obj src\Mw.lib
|
||||
|
||||
examples\basic\radiobox.obj: examples/basic/radiobox.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/radiobox.c
|
||||
|
||||
examples\basic\rotate.exe: examples\basic\rotate.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\rotate.obj src\Mw.lib
|
||||
|
||||
examples\basic\rotate.obj: examples/basic/rotate.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/rotate.c
|
||||
|
||||
examples\basic\scrollbar.exe: examples\basic\scrollbar.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\scrollbar.obj src\Mw.lib
|
||||
|
||||
examples\basic\scrollbar.obj: examples/basic/scrollbar.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/scrollbar.c
|
||||
|
||||
examples\basic\sevensegment.exe: examples\basic\sevensegment.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\sevensegment.obj src\Mw.lib
|
||||
|
||||
examples\basic\sevensegment.obj: examples/basic/sevensegment.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/sevensegment.c
|
||||
|
||||
examples\basic\subwindow.exe: examples\basic\subwindow.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\subwindow.obj src\Mw.lib
|
||||
|
||||
examples\basic\subwindow.obj: examples/basic/subwindow.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/subwindow.c
|
||||
|
||||
examples\basic\tab.exe: examples\basic\tab.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\tab.obj src\Mw.lib
|
||||
|
||||
examples\basic\tab.obj: examples/basic/tab.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/tab.c
|
||||
|
||||
examples\basic\treeview.exe: examples\basic\treeview.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\treeview.obj src\Mw.lib
|
||||
|
||||
examples\basic\treeview.obj: examples/basic/treeview.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/treeview.c
|
||||
|
||||
examples\basic\viewport.exe: examples\basic\viewport.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\basic\viewport.obj src\Mw.lib
|
||||
|
||||
examples\basic\viewport.obj: examples/basic/viewport.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/basic/viewport.c
|
||||
|
||||
examples\gldemos\boing.exe: examples\gldemos\boing.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\gldemos\boing.obj src\Mw.lib opengl32.lib glu32.lib
|
||||
|
||||
examples\gldemos\boing.obj: examples/gldemos/boing.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/boing.c
|
||||
|
||||
examples\gldemos\clock.exe: examples\gldemos\clock.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\gldemos\clock.obj src\Mw.lib opengl32.lib glu32.lib
|
||||
|
||||
examples\gldemos\clock.obj: examples/gldemos/clock.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/clock.c
|
||||
|
||||
examples\gldemos\cube.exe: examples\gldemos\cube.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\gldemos\cube.obj src\Mw.lib opengl32.lib glu32.lib
|
||||
|
||||
examples\gldemos\cube.obj: examples/gldemos/cube.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/cube.c
|
||||
|
||||
examples\gldemos\gears.exe: examples\gldemos\gears.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\gldemos\gears.obj src\Mw.lib opengl32.lib glu32.lib
|
||||
|
||||
examples\gldemos\gears.obj: examples/gldemos/gears.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/gears.c
|
||||
|
||||
examples\gldemos\triangle.exe: examples\gldemos\triangle.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\gldemos\triangle.obj src\Mw.lib opengl32.lib glu32.lib
|
||||
|
||||
examples\gldemos\triangle.obj: examples/gldemos/triangle.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/triangle.c
|
||||
|
||||
examples\gldemos\tripaint.exe: examples\gldemos\tripaint.obj src\Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) /OUT:$@ examples\gldemos\tripaint.obj src\Mw.lib opengl32.lib glu32.lib
|
||||
|
||||
examples\gldemos\tripaint.obj: examples/gldemos/tripaint.c
|
||||
$(CC) $(EXE_CFLAGS) /Fo$@ examples/gldemos/tripaint.c
|
||||
|
||||
|
||||
src\Mw.dll: external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj
|
||||
$(LD) $(MW_LDFLAGS) /OUT:$@ external\libz\src\adler32.obj external\libz\src\compress.obj external\libz\src\crc32.obj external\libz\src\deflate.obj external\libz\src\gzclose.obj external\libz\src\gzlib.obj external\libz\src\gzread.obj external\libz\src\gzwrite.obj external\libz\src\infback.obj external\libz\src\inffast.obj external\libz\src\inflate.obj external\libz\src\inftrees.obj external\libz\src\trees.obj external\libz\src\uncompr.obj external\libz\src\zutil.obj external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\charset.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldmonottf.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\monottf.obj src\text\font\ttf.obj src\text\ft2.obj src\text\gdi.obj src\text\stbtt.obj src\text\text.obj src\truetype.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\calendar.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\subwindow.obj src\widget\tab.obj src\widget\table.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib winmm.lib user32.lib advapi32.lib
|
||||
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(MW_CFLAGS) /Fo$@ $<
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
|
||||
Greetings - Welcome to the Milsko GUI Toolkit (Version 1.4)
|
||||
|
||||
This document contains a brief summary of the contents of this source
|
||||
distributions and building instructions for Milsko GUI Toolkit.
|
||||
|
||||
Requirements
|
||||
|
||||
Milsko requires either
|
||||
* A Windows environment with GDI (so anything NT or 9x)
|
||||
* A Unix-like environment with Wayland and/or X11 for runtime.
|
||||
|
||||
To build Milsko for Windows, you must have one of following compilers:
|
||||
* Visual C++ 6.0 or newer
|
||||
* Borland C++ 5.5 or newer
|
||||
* Open Watcom 2.0 or newer
|
||||
* MinGW-w64
|
||||
|
||||
and for Unix-like and MacOS:
|
||||
* GNU C Compiler
|
||||
* Clang
|
||||
|
||||
|
||||
Contents
|
||||
|
||||
At the top level of this hierarchy there are seven directories:
|
||||
|
||||
src - Contains the source for Milsko library
|
||||
|
||||
include - Contains the headers for Milsko
|
||||
|
||||
doc - Contains the documentation for Milsko
|
||||
|
||||
external - Contains the external dependency that Milsko uses
|
||||
|
||||
resource - Contains the resources used by maintainers
|
||||
|
||||
tools - Contains the tools used by maintainers
|
||||
|
||||
|
||||
Building Milsko
|
||||
|
||||
Building Milsko depends on the platform you use, and the compiler you use.
|
||||
|
||||
A. Visual C++
|
||||
-------------
|
||||
|
||||
1) Run `nmake -f NTMakefile'.
|
||||
|
||||
B. Borland C++
|
||||
--------------
|
||||
|
||||
1) Run `make -f BorMakefile'.
|
||||
|
||||
C. Open Watcom
|
||||
--------------
|
||||
|
||||
1) Run `wmake -f WatMakefile'.
|
||||
|
||||
D. MinGW-w64/GCC/Clang
|
||||
----------------------
|
||||
|
||||
1) Determine if you need Vulkan and/or OpenGL.
|
||||
|
||||
2) Either:
|
||||
a.) Run `./configure'. For help, run `./configure --help'.
|
||||
b.) Use CMake; i.e. `cmake -B build`. (if contributing, name the build
|
||||
folder build as that's what's included in the .gitignore)
|
||||
|
||||
3) Run `make'.
|
||||
|
||||
-- Nishi (nishi@nishi.boats)
|
||||
|
|
@ -1,506 +0,0 @@
|
|||
CC = wcc386 -bt=nt -q
|
||||
LD = wlink option quiet
|
||||
|
||||
MW_CFLAGS = -bd -i=include -i=external/libz/include -d_MILSKO -d_MILSKO_BUILD -dUSE_GDI -dUSE_STB_IMAGE -dSTBI_NO_SIMD -dUSE_GDI_TEXT
|
||||
MW_LDFLAGS = system nt_dll
|
||||
EXE_CFLAGS = -i=include
|
||||
EXE_LDFLAGS = system nt
|
||||
all: src/Mw.dll examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe
|
||||
lib: src/Mw.dll
|
||||
examples: examples/basic/box.exe examples/basic/calculator.exe examples/basic/checkbox.exe examples/basic/clipboard.exe examples/basic/colorpicker.exe examples/basic/combobox.exe examples/basic/example.exe examples/basic/filechooser.exe examples/basic/image.exe examples/basic/listbox.exe examples/basic/messagebox.exe examples/basic/periodic.exe examples/basic/progressbar.exe examples/basic/radiobox.exe examples/basic/rotate.exe examples/basic/scrollbar.exe examples/basic/sevensegment.exe examples/basic/subwindow.exe examples/basic/tab.exe examples/basic/treeview.exe examples/basic/viewport.exe examples/gldemos/boing.exe examples/gldemos/clock.exe examples/gldemos/cube.exe examples/gldemos/gears.exe examples/gldemos/triangle.exe examples/gldemos/tripaint.exe
|
||||
clean: .SYMBOLIC
|
||||
%erase external/libz/src/adler32.obj
|
||||
%erase external/libz/src/compress.obj
|
||||
%erase external/libz/src/crc32.obj
|
||||
%erase external/libz/src/deflate.obj
|
||||
%erase external/libz/src/gzclose.obj
|
||||
%erase external/libz/src/gzlib.obj
|
||||
%erase external/libz/src/gzread.obj
|
||||
%erase external/libz/src/gzwrite.obj
|
||||
%erase external/libz/src/infback.obj
|
||||
%erase external/libz/src/inffast.obj
|
||||
%erase external/libz/src/inflate.obj
|
||||
%erase external/libz/src/inftrees.obj
|
||||
%erase external/libz/src/trees.obj
|
||||
%erase external/libz/src/uncompr.obj
|
||||
%erase external/libz/src/zutil.obj
|
||||
%erase external/stb_ds.obj
|
||||
%erase external/stb_image.obj
|
||||
%erase external/stb_truetype.obj
|
||||
%erase src/abstract/charset.obj
|
||||
%erase src/abstract/directory.obj
|
||||
%erase src/abstract/dynamic.obj
|
||||
%erase src/abstract/time.obj
|
||||
%erase src/backend/gdi.obj
|
||||
%erase src/color.obj
|
||||
%erase src/core.obj
|
||||
%erase src/cursor/arrow.obj
|
||||
%erase src/cursor/cross.obj
|
||||
%erase src/cursor/default.obj
|
||||
%erase src/cursor/hidden.obj
|
||||
%erase src/cursor/text.obj
|
||||
%erase src/default.obj
|
||||
%erase src/dialog/colorpicker.obj
|
||||
%erase src/dialog/directorychooser.obj
|
||||
%erase src/dialog/filechooser.obj
|
||||
%erase src/dialog/messagebox.obj
|
||||
%erase src/draw.obj
|
||||
%erase src/icon/back.obj
|
||||
%erase src/icon/clock.obj
|
||||
%erase src/icon/computer.obj
|
||||
%erase src/icon/directory.obj
|
||||
%erase src/icon/down.obj
|
||||
%erase src/icon/error.obj
|
||||
%erase src/icon/file.obj
|
||||
%erase src/icon/forward.obj
|
||||
%erase src/icon/info.obj
|
||||
%erase src/icon/left.obj
|
||||
%erase src/icon/news.obj
|
||||
%erase src/icon/note.obj
|
||||
%erase src/icon/right.obj
|
||||
%erase src/icon/search.obj
|
||||
%erase src/icon/up.obj
|
||||
%erase src/icon/warning.obj
|
||||
%erase src/lowlevel.obj
|
||||
%erase src/string.obj
|
||||
%erase src/text/font/boldfont.obj
|
||||
%erase src/text/font/boldmonottf.obj
|
||||
%erase src/text/font/boldttf.obj
|
||||
%erase src/text/font/font.obj
|
||||
%erase src/text/font/monottf.obj
|
||||
%erase src/text/font/ttf.obj
|
||||
%erase src/text/ft2.obj
|
||||
%erase src/text/gdi.obj
|
||||
%erase src/text/stbtt.obj
|
||||
%erase src/text/text.obj
|
||||
%erase src/truetype.obj
|
||||
%erase src/unicode.obj
|
||||
%erase src/widget/box.obj
|
||||
%erase src/widget/button.obj
|
||||
%erase src/widget/calendar.obj
|
||||
%erase src/widget/checkbox.obj
|
||||
%erase src/widget/combobox.obj
|
||||
%erase src/widget/entry.obj
|
||||
%erase src/widget/frame.obj
|
||||
%erase src/widget/image.obj
|
||||
%erase src/widget/label.obj
|
||||
%erase src/widget/listbox.obj
|
||||
%erase src/widget/menu.obj
|
||||
%erase src/widget/numberentry.obj
|
||||
%erase src/widget/opengl.obj
|
||||
%erase src/widget/progressbar.obj
|
||||
%erase src/widget/radiobox.obj
|
||||
%erase src/widget/scrollbar.obj
|
||||
%erase src/widget/separator.obj
|
||||
%erase src/widget/submenu.obj
|
||||
%erase src/widget/subwindow.obj
|
||||
%erase src/widget/tab.obj
|
||||
%erase src/widget/table.obj
|
||||
%erase src/widget/treeview.obj
|
||||
%erase src/widget/viewport.obj
|
||||
%erase src/widget/window.obj
|
||||
%erase src/Mw.dll
|
||||
%erase src/Mw.lib
|
||||
%erase examples/basic/box.obj
|
||||
%erase examples/basic/calculator.obj
|
||||
%erase examples/basic/checkbox.obj
|
||||
%erase examples/basic/clipboard.obj
|
||||
%erase examples/basic/colorpicker.obj
|
||||
%erase examples/basic/combobox.obj
|
||||
%erase examples/basic/example.obj
|
||||
%erase examples/basic/filechooser.obj
|
||||
%erase examples/basic/image.obj
|
||||
%erase examples/basic/listbox.obj
|
||||
%erase examples/basic/messagebox.obj
|
||||
%erase examples/basic/periodic.obj
|
||||
%erase examples/basic/progressbar.obj
|
||||
%erase examples/basic/radiobox.obj
|
||||
%erase examples/basic/rotate.obj
|
||||
%erase examples/basic/scrollbar.obj
|
||||
%erase examples/basic/sevensegment.obj
|
||||
%erase examples/basic/subwindow.obj
|
||||
%erase examples/basic/tab.obj
|
||||
%erase examples/basic/treeview.obj
|
||||
%erase examples/basic/viewport.obj
|
||||
%erase examples/gldemos/boing.obj
|
||||
%erase examples/gldemos/clock.obj
|
||||
%erase examples/gldemos/cube.obj
|
||||
%erase examples/gldemos/gears.obj
|
||||
%erase examples/gldemos/triangle.obj
|
||||
%erase examples/gldemos/tripaint.obj
|
||||
%erase examples/basic/box.exe
|
||||
%erase examples/basic/calculator.exe
|
||||
%erase examples/basic/checkbox.exe
|
||||
%erase examples/basic/clipboard.exe
|
||||
%erase examples/basic/colorpicker.exe
|
||||
%erase examples/basic/combobox.exe
|
||||
%erase examples/basic/example.exe
|
||||
%erase examples/basic/filechooser.exe
|
||||
%erase examples/basic/image.exe
|
||||
%erase examples/basic/listbox.exe
|
||||
%erase examples/basic/messagebox.exe
|
||||
%erase examples/basic/periodic.exe
|
||||
%erase examples/basic/progressbar.exe
|
||||
%erase examples/basic/radiobox.exe
|
||||
%erase examples/basic/rotate.exe
|
||||
%erase examples/basic/scrollbar.exe
|
||||
%erase examples/basic/sevensegment.exe
|
||||
%erase examples/basic/subwindow.exe
|
||||
%erase examples/basic/tab.exe
|
||||
%erase examples/basic/treeview.exe
|
||||
%erase examples/basic/viewport.exe
|
||||
%erase examples/gldemos/boing.exe
|
||||
%erase examples/gldemos/clock.exe
|
||||
%erase examples/gldemos/cube.exe
|
||||
%erase examples/gldemos/gears.exe
|
||||
%erase examples/gldemos/triangle.exe
|
||||
%erase examples/gldemos/tripaint.exe
|
||||
|
||||
examples/basic/box.exe: examples/basic/box.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/box.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/box.obj: examples/basic/box.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/box.c
|
||||
|
||||
examples/basic/calculator.exe: examples/basic/calculator.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/calculator.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/calculator.obj: examples/basic/calculator.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/calculator.c
|
||||
|
||||
examples/basic/checkbox.exe: examples/basic/checkbox.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/checkbox.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/checkbox.obj: examples/basic/checkbox.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/checkbox.c
|
||||
|
||||
examples/basic/clipboard.exe: examples/basic/clipboard.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/clipboard.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/clipboard.obj: examples/basic/clipboard.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/clipboard.c
|
||||
|
||||
examples/basic/colorpicker.exe: examples/basic/colorpicker.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/colorpicker.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/colorpicker.obj: examples/basic/colorpicker.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/colorpicker.c
|
||||
|
||||
examples/basic/combobox.exe: examples/basic/combobox.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/combobox.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/combobox.obj: examples/basic/combobox.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/combobox.c
|
||||
|
||||
examples/basic/example.exe: examples/basic/example.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/example.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/example.obj: examples/basic/example.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/example.c
|
||||
|
||||
examples/basic/filechooser.exe: examples/basic/filechooser.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/filechooser.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/filechooser.obj: examples/basic/filechooser.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/filechooser.c
|
||||
|
||||
examples/basic/image.exe: examples/basic/image.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/image.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/image.obj: examples/basic/image.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/image.c
|
||||
|
||||
examples/basic/listbox.exe: examples/basic/listbox.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/listbox.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/listbox.obj: examples/basic/listbox.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/listbox.c
|
||||
|
||||
examples/basic/messagebox.exe: examples/basic/messagebox.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/messagebox.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/messagebox.obj: examples/basic/messagebox.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/messagebox.c
|
||||
|
||||
examples/basic/periodic.exe: examples/basic/periodic.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/periodic.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/periodic.obj: examples/basic/periodic.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/periodic.c
|
||||
|
||||
examples/basic/progressbar.exe: examples/basic/progressbar.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/progressbar.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/progressbar.obj: examples/basic/progressbar.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/progressbar.c
|
||||
|
||||
examples/basic/radiobox.exe: examples/basic/radiobox.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/radiobox.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/radiobox.obj: examples/basic/radiobox.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/radiobox.c
|
||||
|
||||
examples/basic/rotate.exe: examples/basic/rotate.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/rotate.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/rotate.obj: examples/basic/rotate.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/rotate.c
|
||||
|
||||
examples/basic/scrollbar.exe: examples/basic/scrollbar.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/scrollbar.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/scrollbar.obj: examples/basic/scrollbar.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/scrollbar.c
|
||||
|
||||
examples/basic/sevensegment.exe: examples/basic/sevensegment.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/sevensegment.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/sevensegment.obj: examples/basic/sevensegment.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/sevensegment.c
|
||||
|
||||
examples/basic/subwindow.exe: examples/basic/subwindow.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/subwindow.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/subwindow.obj: examples/basic/subwindow.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/subwindow.c
|
||||
|
||||
examples/basic/tab.exe: examples/basic/tab.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/tab.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/tab.obj: examples/basic/tab.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/tab.c
|
||||
|
||||
examples/basic/treeview.exe: examples/basic/treeview.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/treeview.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/treeview.obj: examples/basic/treeview.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/treeview.c
|
||||
|
||||
examples/basic/viewport.exe: examples/basic/viewport.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/basic/viewport.obj library clib3r.lib library src/Mw.lib
|
||||
|
||||
examples/basic/viewport.obj: examples/basic/viewport.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/basic/viewport.c
|
||||
|
||||
examples/gldemos/boing.exe: examples/gldemos/boing.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/gldemos/boing.obj library clib3r.lib library src/Mw.lib library opengl32.lib library glu32.lib
|
||||
|
||||
examples/gldemos/boing.obj: examples/gldemos/boing.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/boing.c
|
||||
|
||||
examples/gldemos/clock.exe: examples/gldemos/clock.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/gldemos/clock.obj library clib3r.lib library src/Mw.lib library opengl32.lib library glu32.lib
|
||||
|
||||
examples/gldemos/clock.obj: examples/gldemos/clock.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/clock.c
|
||||
|
||||
examples/gldemos/cube.exe: examples/gldemos/cube.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/gldemos/cube.obj library clib3r.lib library src/Mw.lib library opengl32.lib library glu32.lib
|
||||
|
||||
examples/gldemos/cube.obj: examples/gldemos/cube.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/cube.c
|
||||
|
||||
examples/gldemos/gears.exe: examples/gldemos/gears.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/gldemos/gears.obj library clib3r.lib library src/Mw.lib library opengl32.lib library glu32.lib
|
||||
|
||||
examples/gldemos/gears.obj: examples/gldemos/gears.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/gears.c
|
||||
|
||||
examples/gldemos/triangle.exe: examples/gldemos/triangle.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/gldemos/triangle.obj library clib3r.lib library src/Mw.lib library opengl32.lib library glu32.lib
|
||||
|
||||
examples/gldemos/triangle.obj: examples/gldemos/triangle.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/triangle.c
|
||||
|
||||
examples/gldemos/tripaint.exe: examples/gldemos/tripaint.obj src/Mw.dll
|
||||
$(LD) $(EXE_LDFLAGS) name $@ file examples/gldemos/tripaint.obj library clib3r.lib library src/Mw.lib library opengl32.lib library glu32.lib
|
||||
|
||||
examples/gldemos/tripaint.obj: examples/gldemos/tripaint.c
|
||||
$(CC) $(EXE_CFLAGS) -fo=$@ examples/gldemos/tripaint.c
|
||||
|
||||
|
||||
src/Mw.dll: external/libz/src/adler32.obj external/libz/src/compress.obj external/libz/src/crc32.obj external/libz/src/deflate.obj external/libz/src/gzclose.obj external/libz/src/gzlib.obj external/libz/src/gzread.obj external/libz/src/gzwrite.obj external/libz/src/infback.obj external/libz/src/inffast.obj external/libz/src/inflate.obj external/libz/src/inftrees.obj external/libz/src/trees.obj external/libz/src/uncompr.obj external/libz/src/zutil.obj external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/charset.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldmonottf.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/monottf.obj src/text/font/ttf.obj src/text/ft2.obj src/text/gdi.obj src/text/stbtt.obj src/text/text.obj src/truetype.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/calendar.obj src/widget/checkbox.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/subwindow.obj src/widget/tab.obj src/widget/table.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj
|
||||
$(LD) $(MW_LDFLAGS) option implib=src/Mw.lib name $@ file external/libz/src/adler32.obj file external/libz/src/compress.obj file external/libz/src/crc32.obj file external/libz/src/deflate.obj file external/libz/src/gzclose.obj file external/libz/src/gzlib.obj file external/libz/src/gzread.obj file external/libz/src/gzwrite.obj file external/libz/src/infback.obj file external/libz/src/inffast.obj file external/libz/src/inflate.obj file external/libz/src/inftrees.obj file external/libz/src/trees.obj file external/libz/src/uncompr.obj file external/libz/src/zutil.obj file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/charset.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldmonottf.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/monottf.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/gdi.obj file src/text/stbtt.obj file src/text/text.obj file src/truetype.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/calendar.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/subwindow.obj file src/widget/tab.obj file src/widget/table.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library winmm.lib library user32.lib library advapi32.lib
|
||||
|
||||
|
||||
|
||||
external/libz/src/adler32.obj: external/libz/src/adler32.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/adler32.c
|
||||
external/libz/src/compress.obj: external/libz/src/compress.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/compress.c
|
||||
external/libz/src/crc32.obj: external/libz/src/crc32.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/crc32.c
|
||||
external/libz/src/deflate.obj: external/libz/src/deflate.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/deflate.c
|
||||
external/libz/src/gzclose.obj: external/libz/src/gzclose.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/gzclose.c
|
||||
external/libz/src/gzlib.obj: external/libz/src/gzlib.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/gzlib.c
|
||||
external/libz/src/gzread.obj: external/libz/src/gzread.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/gzread.c
|
||||
external/libz/src/gzwrite.obj: external/libz/src/gzwrite.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/gzwrite.c
|
||||
external/libz/src/infback.obj: external/libz/src/infback.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/infback.c
|
||||
external/libz/src/inffast.obj: external/libz/src/inffast.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/inffast.c
|
||||
external/libz/src/inflate.obj: external/libz/src/inflate.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/inflate.c
|
||||
external/libz/src/inftrees.obj: external/libz/src/inftrees.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/inftrees.c
|
||||
external/libz/src/trees.obj: external/libz/src/trees.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/trees.c
|
||||
external/libz/src/uncompr.obj: external/libz/src/uncompr.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/uncompr.c
|
||||
external/libz/src/zutil.obj: external/libz/src/zutil.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/libz/src/zutil.c
|
||||
external/stb_ds.obj: external/stb_ds.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/stb_ds.c
|
||||
external/stb_image.obj: external/stb_image.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/stb_image.c
|
||||
external/stb_truetype.obj: external/stb_truetype.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ external/stb_truetype.c
|
||||
src/abstract/charset.obj: src/abstract/charset.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/abstract/charset.c
|
||||
src/abstract/directory.obj: src/abstract/directory.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/abstract/directory.c
|
||||
src/abstract/dynamic.obj: src/abstract/dynamic.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/abstract/dynamic.c
|
||||
src/abstract/time.obj: src/abstract/time.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/abstract/time.c
|
||||
src/backend/gdi.obj: src/backend/gdi.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/backend/gdi.c
|
||||
src/color.obj: src/color.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/color.c
|
||||
src/core.obj: src/core.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/core.c
|
||||
src/cursor/arrow.obj: src/cursor/arrow.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/cursor/arrow.c
|
||||
src/cursor/cross.obj: src/cursor/cross.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/cursor/cross.c
|
||||
src/cursor/default.obj: src/cursor/default.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/cursor/default.c
|
||||
src/cursor/hidden.obj: src/cursor/hidden.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/cursor/hidden.c
|
||||
src/cursor/text.obj: src/cursor/text.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/cursor/text.c
|
||||
src/default.obj: src/default.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/default.c
|
||||
src/dialog/colorpicker.obj: src/dialog/colorpicker.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/dialog/colorpicker.c
|
||||
src/dialog/directorychooser.obj: src/dialog/directorychooser.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/dialog/directorychooser.c
|
||||
src/dialog/filechooser.obj: src/dialog/filechooser.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/dialog/filechooser.c
|
||||
src/dialog/messagebox.obj: src/dialog/messagebox.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/dialog/messagebox.c
|
||||
src/draw.obj: src/draw.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/draw.c
|
||||
src/icon/back.obj: src/icon/back.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/back.c
|
||||
src/icon/clock.obj: src/icon/clock.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/clock.c
|
||||
src/icon/computer.obj: src/icon/computer.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/computer.c
|
||||
src/icon/directory.obj: src/icon/directory.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/directory.c
|
||||
src/icon/down.obj: src/icon/down.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/down.c
|
||||
src/icon/error.obj: src/icon/error.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/error.c
|
||||
src/icon/file.obj: src/icon/file.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/file.c
|
||||
src/icon/forward.obj: src/icon/forward.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/forward.c
|
||||
src/icon/info.obj: src/icon/info.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/info.c
|
||||
src/icon/left.obj: src/icon/left.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/left.c
|
||||
src/icon/news.obj: src/icon/news.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/news.c
|
||||
src/icon/note.obj: src/icon/note.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/note.c
|
||||
src/icon/right.obj: src/icon/right.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/right.c
|
||||
src/icon/search.obj: src/icon/search.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/search.c
|
||||
src/icon/up.obj: src/icon/up.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/up.c
|
||||
src/icon/warning.obj: src/icon/warning.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/icon/warning.c
|
||||
src/lowlevel.obj: src/lowlevel.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/lowlevel.c
|
||||
src/string.obj: src/string.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/string.c
|
||||
src/text/font/boldfont.obj: src/text/font/boldfont.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/font/boldfont.c
|
||||
src/text/font/boldmonottf.obj: src/text/font/boldmonottf.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/font/boldmonottf.c
|
||||
src/text/font/boldttf.obj: src/text/font/boldttf.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/font/boldttf.c
|
||||
src/text/font/font.obj: src/text/font/font.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/font/font.c
|
||||
src/text/font/monottf.obj: src/text/font/monottf.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/font/monottf.c
|
||||
src/text/font/ttf.obj: src/text/font/ttf.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/font/ttf.c
|
||||
src/text/ft2.obj: src/text/ft2.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/ft2.c
|
||||
src/text/gdi.obj: src/text/gdi.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/gdi.c
|
||||
src/text/stbtt.obj: src/text/stbtt.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/stbtt.c
|
||||
src/text/text.obj: src/text/text.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/text/text.c
|
||||
src/truetype.obj: src/truetype.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/truetype.c
|
||||
src/unicode.obj: src/unicode.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/unicode.c
|
||||
src/widget/box.obj: src/widget/box.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/box.c
|
||||
src/widget/button.obj: src/widget/button.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/button.c
|
||||
src/widget/calendar.obj: src/widget/calendar.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/calendar.c
|
||||
src/widget/checkbox.obj: src/widget/checkbox.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/checkbox.c
|
||||
src/widget/combobox.obj: src/widget/combobox.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/combobox.c
|
||||
src/widget/entry.obj: src/widget/entry.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/entry.c
|
||||
src/widget/frame.obj: src/widget/frame.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/frame.c
|
||||
src/widget/image.obj: src/widget/image.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/image.c
|
||||
src/widget/label.obj: src/widget/label.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/label.c
|
||||
src/widget/listbox.obj: src/widget/listbox.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/listbox.c
|
||||
src/widget/menu.obj: src/widget/menu.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/menu.c
|
||||
src/widget/numberentry.obj: src/widget/numberentry.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/numberentry.c
|
||||
src/widget/opengl.obj: src/widget/opengl.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/opengl.c
|
||||
src/widget/progressbar.obj: src/widget/progressbar.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/progressbar.c
|
||||
src/widget/radiobox.obj: src/widget/radiobox.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/radiobox.c
|
||||
src/widget/scrollbar.obj: src/widget/scrollbar.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/scrollbar.c
|
||||
src/widget/separator.obj: src/widget/separator.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/separator.c
|
||||
src/widget/submenu.obj: src/widget/submenu.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/submenu.c
|
||||
src/widget/subwindow.obj: src/widget/subwindow.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/subwindow.c
|
||||
src/widget/tab.obj: src/widget/tab.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/tab.c
|
||||
src/widget/table.obj: src/widget/table.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/table.c
|
||||
src/widget/treeview.obj: src/widget/treeview.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/treeview.c
|
||||
src/widget/viewport.obj: src/widget/viewport.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/viewport.c
|
||||
src/widget/window.obj: src/widget/window.c
|
||||
$(CC) $(MW_CFLAGS) -fo=$@ src/widget/window.c
|
||||
363
widget/milsko/milskosrc/configure
vendored
363
widget/milsko/milskosrc/configure
vendored
|
|
@ -1,363 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
our $target = `uname -s`;
|
||||
$target =~ s/\r?\n$//;
|
||||
|
||||
# MSYS with MinGW gives us some other shit idk
|
||||
if (index($target, "MINGW") != -1) {
|
||||
$target = "Windows";
|
||||
}
|
||||
|
||||
foreach my $l (@ARGV) {
|
||||
if ($l =~ /^--.+$/) {
|
||||
}
|
||||
elsif ($l =~ /^(.+)=(.+)$/) {
|
||||
$ENV{$1} = $2;
|
||||
}
|
||||
}
|
||||
|
||||
our $prefix = "/usr/local";
|
||||
our $cc = defined($ENV{CC}) ? $ENV{CC} : "*host*gcc";
|
||||
our $cxx = defined($ENV{CXX}) ? $ENV{CXX} : "*host*g++";
|
||||
our $ar = defined($ENV{AR}) ? $ENV{AR} : "*host*ar";
|
||||
our $incdir = "-I include";
|
||||
our $incdir2 = "";
|
||||
our $cflags = "-fPIC -D_MILSKO -D_MILSKO_BUILD -fvisibility=hidden";
|
||||
our $libdir = "";
|
||||
our $ldflags = "";
|
||||
our $math = "-lm";
|
||||
our @shared = "-shared";
|
||||
our @backends = ();
|
||||
|
||||
our $library_prefix = "lib";
|
||||
our $library_suffix = ".so";
|
||||
our $object_suffix = ".o";
|
||||
our $executable_suffix = "";
|
||||
|
||||
our @library_targets = ();
|
||||
our @examples_targets = ();
|
||||
our %examples_libs = ();
|
||||
|
||||
our $cross = 0;
|
||||
our $host = "";
|
||||
|
||||
require("./pl/utils.pl");
|
||||
|
||||
param_set("classic-theme", 0);
|
||||
param_set("stb-image", 1);
|
||||
param_set("opengl", 0);
|
||||
param_set("vulkan", 0);
|
||||
param_set("vulkan-string-helper", 1);
|
||||
param_set("shared", 1);
|
||||
param_set("static", 1);
|
||||
param_set("examples", 1);
|
||||
|
||||
# (option that only makes sense on x11)
|
||||
param_set("allow-sloppy-focus", 0);
|
||||
|
||||
my %features = (
|
||||
"classic-theme" => "use classic theme",
|
||||
"stb-image" => "use stb_image, instead use libjpeg/libpng",
|
||||
"stb-truetype" => "use stb_truetype",
|
||||
"freetype2" => "use FreeType2",
|
||||
"gdi-text" => "(Windows only) use GDI Text",
|
||||
"xrender" => "(X11 only) use XRender",
|
||||
"opengl" => "build OpenGL widget",
|
||||
"vulkan" => "build Vulkan widget",
|
||||
"vulkan-string-helper" => "use Vulkan string helper",
|
||||
"shared" => "build shared library",
|
||||
"static" => "build static library",
|
||||
"wayland" => "enable wayland backend",
|
||||
"gnustep" => "use gnustep",
|
||||
"dbus" => "use DBus on supported platform",
|
||||
"allow-sloppy-focus" => "prevent the x11 backend from using XSetInputFocus to enforce click-to-focus"
|
||||
);
|
||||
my @features_keys = (
|
||||
"1classic-theme", "1stb-image",
|
||||
"1stb-truetype", "1freetype2", "1gdi-text",
|
||||
"1opengl", "2xrender",
|
||||
"1vulkan", "2vulkan-string-helper",
|
||||
"1shared", "1static",
|
||||
"1wayland", "1gnustep",
|
||||
"1dbus"
|
||||
);
|
||||
|
||||
sub def_platform {
|
||||
if($target eq "Windows") {
|
||||
param_set("freetype2", 0);
|
||||
param_set("stb-truetype", 0);
|
||||
} elsif($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Haiku") {
|
||||
param_set("freetype2", 1);
|
||||
param_set("stb-truetype", 0);
|
||||
} else {
|
||||
param_set("freetype2", 0);
|
||||
param_set("stb-truetype", 1);
|
||||
}
|
||||
if($target eq "Linux" || $target eq "FreeBSD") {
|
||||
param_set("x11", 1);
|
||||
param_set("xrender", 1);
|
||||
if(!param_get("tiny")){
|
||||
param_set("wayland", 1);
|
||||
}
|
||||
param_set("dbus", 1);
|
||||
}
|
||||
if($target eq "NetBSD" || $target eq "OpenBSD") {
|
||||
param_set("x11", 1);
|
||||
}
|
||||
if($target eq "Windows") {
|
||||
param_set("gdi-text", 1);
|
||||
} else {
|
||||
param_set("gdi-text", 0);
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $l (@ARGV) {
|
||||
if ($l =~ /^--target=(.+)$/) {
|
||||
$target = $1;
|
||||
}
|
||||
}
|
||||
|
||||
def_platform();
|
||||
|
||||
|
||||
foreach my $l (@ARGV) {
|
||||
if ($l =~ /^--with-([^=]+)=(.+)$/) {
|
||||
param_set($1, $2);
|
||||
}
|
||||
elsif ($l =~ /^--(?:with|enable)-(.+)$/) {
|
||||
param_set($1, 1);
|
||||
}
|
||||
elsif ($l =~ /^--(?:without|disable)-(.+)$/) {
|
||||
param_set($1, 0);
|
||||
}
|
||||
elsif ($l =~ /^--host=(.+)$/) {
|
||||
$host = $1 . "-";
|
||||
}
|
||||
elsif ($l =~ /^--cflags=(.+)$/) {
|
||||
add_cflags($1);
|
||||
}
|
||||
elsif ($l eq "--cross") {
|
||||
$cross = 1;
|
||||
}
|
||||
elsif ($l eq "--tiny") {
|
||||
param_set("tiny",1);
|
||||
}
|
||||
elsif (($l eq "-h") or ($l eq "--help")) {
|
||||
print("Milsko Toolkit Configuration Utility\n");
|
||||
print("\n");
|
||||
print("Usage: $0 [options]\n");
|
||||
print("\n");
|
||||
print("Options:\n");
|
||||
print(" -h --help Display this help\n");
|
||||
print(" --prefix=PREFIX Installation prefix\n");
|
||||
print(" --host=TARGET Host for compiler/archiver\n");
|
||||
print(" --target=TARGET Specify target\n");
|
||||
print(" --cflags=CFLAGS Add cflags\n");
|
||||
print(" --tiny Build smallest possible library\n");
|
||||
print(" --cross Indicate cross compilation\n");
|
||||
print("\n");
|
||||
print("Features:\n");
|
||||
print(" --enable-FEATURE Use FEATURE\n");
|
||||
print(" --with-FEATURE Use FEATURE\n");
|
||||
print(" --disable-FEATURE Do not use FEATURE\n");
|
||||
print(" --without-FEATURE Do not use FEATURE\n");
|
||||
|
||||
foreach my $l (@features_keys) {
|
||||
my $flag = (
|
||||
(substr($l, 0, 1) eq '1')
|
||||
? (param_get(substr($l, 1)) ? "--disable-" : "--enable-")
|
||||
: (param_get(substr($l, 1)) ? "--without-" : "--with-")
|
||||
) . substr($l, 1);
|
||||
my $do = param_get(substr($l, 1)) ? "Do not " : "";
|
||||
my $feat = $features{ substr($l, 1) };
|
||||
if (not(param_get(substr($l, 1)))) {
|
||||
$feat = uc(substr($feat, 0, 1)) . substr($feat, 1);
|
||||
}
|
||||
print(" $flag" . (" " x (32 - length($flag))) . "${do}${feat}\n");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (-f "./pl/ostype/${target}.pl") {
|
||||
require("./pl/ostype/${target}.pl");
|
||||
}
|
||||
else {
|
||||
print(
|
||||
"Perl file (pl/ostype/${target}.pl) was not found for your target. Please add one.\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require("./pl/rules.pl");
|
||||
|
||||
print("Target : " . $target . "\n");
|
||||
|
||||
my @l = ();
|
||||
foreach my $e (param_list()) {
|
||||
if (not(param_get($e))) {
|
||||
next;
|
||||
}
|
||||
if (($e eq "vulkan-string-helper") and param_get("vulkan")) {
|
||||
push(@l, $e);
|
||||
}
|
||||
elsif (($e eq "xrender") and ($backend eq "x11")) {
|
||||
push(@l, $e);
|
||||
}
|
||||
elsif (not($e eq "vulkan-string-helper") and not($e eq "xrender")) {
|
||||
push(@l, $e);
|
||||
}
|
||||
}
|
||||
print("Enabled: " . join(" ", @l) . "\n");
|
||||
|
||||
$cc =~ s/\*host\*/$host/;
|
||||
$cxx =~ s/\*host\*/$host/;
|
||||
$ar =~ s/\*host\*/$host/;
|
||||
|
||||
open(OUT, ">", "Makefile");
|
||||
print(OUT "PREFIX = ${prefix}\n");
|
||||
print(OUT "AR = ${ar}\n");
|
||||
print(OUT "CC = ${cc}\n");
|
||||
print(OUT "CXX = ${cxx}\n");
|
||||
print(OUT "INCDIR = ${incdir} ${incdir2}\n");
|
||||
print(OUT "CFLAGS = ${cflags}\n");
|
||||
print(OUT "LIBDIR = ${libdir}\n");
|
||||
print(OUT "LDFLAGS = ${ldflags}\n");
|
||||
print(OUT "LIBS = ${math} ${libs}\n");
|
||||
print(OUT "MATH = ${math}\n");
|
||||
print(OUT "SHARED = @{shared}\n");
|
||||
print(OUT "\n");
|
||||
print(OUT ".PHONY: all format clean distclean lib examples install\n");
|
||||
print(OUT "\n");
|
||||
print(OUT "all: lib examples\n");
|
||||
print(OUT "\n");
|
||||
print(OUT "install: lib\n");
|
||||
print(OUT
|
||||
" mkdir -p \$(DESTDIR)\$(PREFIX)/lib \$(DESTDIR)\$(PREFIX)/include\n");
|
||||
print(OUT
|
||||
" -cp src/${library_prefix}Mw${library_suffix} \$(DESTDIR)\$(PREFIX)/lib/\n"
|
||||
);
|
||||
print(OUT " -cp src/libMw.a \$(DESTDIR)\$(PREFIX)/lib/\n");
|
||||
print(OUT " cp -rf include \$(DESTDIR)\$(PREFIX)/\n");
|
||||
print(OUT "\n");
|
||||
print(OUT "format:\n");
|
||||
print(OUT
|
||||
" clang-format --verbose -i `find tools src include examples \"(\" -name \"*.c\" -or -name \"*.cc\" -or -name \"*.h\" -or -name \"*.m\" \")\" -and -not -name \"*ttf.c\"`\n"
|
||||
);
|
||||
print(OUT
|
||||
" perltidy -b -bext=\"/\" --paren-tightness=2 `find tools pl configure -name \"*.pl\"`\n"
|
||||
);
|
||||
print(OUT "\n");
|
||||
print(OUT "lib:");
|
||||
|
||||
if (param_get("shared")) {
|
||||
print(OUT " src/${library_prefix}Mw${library_suffix}");
|
||||
}
|
||||
if (param_get("static")) {
|
||||
print(OUT " src/libMw.a");
|
||||
}
|
||||
print(OUT "\n");
|
||||
print(OUT "\n");
|
||||
if (param_get("shared")) {
|
||||
my $linker = "CC";
|
||||
if (grep(/^haiku$/, @backends)) {
|
||||
$linker = "CXX";
|
||||
}
|
||||
print( OUT "src/${library_prefix}Mw${library_suffix}: "
|
||||
. join(" ", @library_targets)
|
||||
. "\n");
|
||||
print(OUT
|
||||
" \$($linker) \$(SHARED) \$(LDFLAGS\) \$(LIBDIR) -o src/${library_prefix}Mw${library_suffix} "
|
||||
. join(" ", @library_targets)
|
||||
. " \$(LIBS)\n");
|
||||
print(OUT "\n");
|
||||
}
|
||||
if (param_get("static")) {
|
||||
print(OUT "src/libMw.a: " . join(" ", @library_targets) . "\n");
|
||||
print(OUT " \$(AR) rcs src/libMw.a " . join(" ", @library_targets) . "\n");
|
||||
}
|
||||
|
||||
foreach my $l (@library_targets) {
|
||||
my $warn = "-Wall -Wextra -Wno-sign-compare -Wno-unused-value";
|
||||
my $s = $l;
|
||||
my $compiler = "CC";
|
||||
my $o = $object_suffix;
|
||||
$o =~ s/\./\\\./g;
|
||||
|
||||
if ($l =~ /cocoa/) {
|
||||
$s =~ s/$o$/.m/;
|
||||
}
|
||||
elsif ($l =~ /haiku/) {
|
||||
$s =~ s/$o$/.cc/;
|
||||
$compiler = "CXX";
|
||||
}
|
||||
else {
|
||||
$s =~ s/$o$/.c/;
|
||||
}
|
||||
|
||||
if ($l =~ /^external\//) {
|
||||
$warn = "";
|
||||
}
|
||||
|
||||
print(OUT "${l}: ${s}\n");
|
||||
print(OUT " \$($compiler) $warn \$\(INCDIR) \$(CFLAGS\) -c -o ${l} ${s}\n");
|
||||
}
|
||||
print(OUT "\n");
|
||||
print(OUT "\n");
|
||||
if (param_get("examples")) {
|
||||
print(OUT "examples: " . join(" ", @examples_targets) . "\n");
|
||||
print(OUT "\n");
|
||||
foreach my $l (@examples_targets) {
|
||||
my $libs = "";
|
||||
my $s = $l;
|
||||
my $o = $executable_suffix;
|
||||
$o =~ s/\./\\\./g;
|
||||
$s =~ s/$o$//;
|
||||
|
||||
if (defined($examples_libs{$l})) {
|
||||
$libs = $examples_libs{$l};
|
||||
}
|
||||
|
||||
if (param_get("shared")) {
|
||||
print(OUT
|
||||
"${l}: ${s}${object_suffix} src/${library_prefix}Mw${library_suffix}\n"
|
||||
);
|
||||
} else {
|
||||
print(OUT
|
||||
"${l}: ${s}${object_suffix} src/${library_prefix}Mw.a\n"
|
||||
);
|
||||
}
|
||||
if (grep(/^cocoa$/, @backends)) {
|
||||
print(OUT
|
||||
" \$(CC) -L./src \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n"
|
||||
);
|
||||
}
|
||||
else {
|
||||
print(OUT
|
||||
" \$(CC) -L src -Wl,-R./src \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n"
|
||||
);
|
||||
}
|
||||
|
||||
if($target eq "ClassicMacOS") {
|
||||
print(OUT
|
||||
" ".$ENV{RETRO68_TOOLCHAIN_PATH}."/bin/MakePEF ${l} -o ${s}.pef\n");
|
||||
print(OUT
|
||||
" Rez -I ".$ENV{RETRO68_TOOLCHAIN_PATH}."/RIncludes ".$ENV{RETRO68_TOOLCHAIN_PATH}."/RIncludes/Retro68APPL.r -DCFRAG_NAME=\"example\" --data ${l}.pef --cc ${l}.dsk -t APPL\n"
|
||||
);
|
||||
}
|
||||
|
||||
print(OUT "${s}${object_suffix}: ${s}.c\n");
|
||||
print(OUT
|
||||
" \$(CC) -c \$\(INCDIR) -o ${s}${object_suffix} ${s}.c -lMw ${math}\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
print(OUT "\n");
|
||||
print(OUT "clean:\n");
|
||||
print(OUT
|
||||
" rm -f */*.o */*/*.o */*/*/*.o */*.exe */*/*.exe */*/*/*.exe src/*.so src/*.dll src/*.dylib src/*.a "
|
||||
. join(" ", @examples_targets)
|
||||
. "\n");
|
||||
print(OUT "\n");
|
||||
print(OUT "distclean: clean\n");
|
||||
print(OUT " rm -f Makefile\n");
|
||||
close(OUT);
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
# Backend dev
|
||||
|
||||
The basic process of creating a new Milsko backend is
|
||||
|
||||
- Adding a new include header into `include/Mw/LowLevel`. It must include;
|
||||
- `struct _MwLLBackendName`: Any details about a window or a subwidget
|
||||
- `struct _MwLLBackendNameColor`: An 8-bit RGB Color. You'll probably never impl this, this is for platforms like X11/GDI where they have a secondary color representation that can be stored.
|
||||
- `struct _MwLLBackendNamePixmap`: Self-explanatory. This is also used for the soft gradients in the modern theme.
|
||||
- `MwLLBackendNameCallInitImpl(void)` called by `MwLibraryInit` to address and platform globals.
|
||||
- Note that all of those structs are actually unions. They should all start with their `MwLLCommon...` equivalants.
|
||||
- Fill out `Mw/LowLevel.h` appopriately, adding an include to your new file and the structs in the appropriate unions. These need to be guarded by a `USE_BACKENDNAME` macro which you'll define later when you modify the build system.
|
||||
- Creating a new impl file in `src/backend`
|
||||
- Backends actually return a table of function pointers that you have to implement with static functions. Your file should end with `#include "call.c"` and then `CALL(BackendName);`, and somewhere you should have the impl for `MwLLBackendNameCallInitImpl(void)`.
|
||||
- Prefer to keep the backend file to one file if you can, though obviously exceptions like the Wayland backend exist because it's simply too complex to sanely stuff into one file.
|
||||
- Add `MwLLBackendNameCallInitImpl` to the `MwLibraryInit` impl in `src/core.c`.
|
||||
- Add a new enum variation to `MwLLBackends` in `Mw/Include/LowLevel.h`; your impl of `MwLLCreateImpl` will set `common.type` to this so the user can check which backend they're on (important for platforms with multiple supported backends).
|
||||
- Either
|
||||
- a.) Modify `CMakeLists.txt` for your platform.
|
||||
- b.) Add a new perl file in `pl/ostype` that `./configure` can reference, and modify `pl/rules.pl`; If you don't know how to use perl it's fine, just copy a file like the `Linux.pl` or `Windows.pl`, the functions you'll have to change for your platform are self explanatory. Ensure it ends with `1;`.
|
||||
- c.) Both.
|
||||
- Both are recommended, but some platforms like Classic Mac OS can't be used with the `./configure` script, and that's fine.
|
||||
|
||||
The functions you'll have to impl are too many to list here so you should start by just copying `x11.c` and then replacing all the function impls with your own.
|
||||
|
||||
\*\*Pay attention to some of these functions' comments in LowLevel.h as they might not be as you expect; for example, `MwLLSetDarkThemeImpl` is for setting the accent color to dark theme on platforms like modern Windows (dark theme itself is set with `MwSetInteger(handle, MwNdarktheme, 1)`).
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
# Writing a new widget
|
||||
@warning This is mainly for developers
|
||||
|
||||
1. Create new file in src/widget with lower case
|
||||
2. Create new header in include/Mw/Widget with pascal case
|
||||
3. Add the header include to include/Mw/Milsko.h, if new widget does not require some extension (like OpenGL and Vulkan)
|
||||
4. See another widget for example
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
# Tiers
|
||||
|
||||
Ports of Milsko are grouped into three "tiers" in terms of their support.
|
||||
|
||||
- **Tier 1**: Before every new release of Milsko, these platforms will be tested to make sure they have full support, and the CI will test them.
|
||||
- **Tier 2**: These might be outdated or not updated in awhile, they might only compile under a specific version/commit of Milsko. Authors of these backends will be made aware of these updates.
|
||||
- **Tier 3**: These are outright unfinished. Only use these if you're a developer.
|
||||
|
||||
Currently, the Tier 1 backends are:
|
||||
|
||||
- Windows 9x+/NT 4.0+
|
||||
- Any Unix/Linux system that supports X11 or Wayland.
|
||||
|
||||
There are currently no Tier 2 backends.
|
||||
|
||||
Tier 3 backends are:
|
||||
|
||||
- Mac OS X 10.4+ with Cocoa
|
||||
- Mac OS 7-9, PowerPC (68k support not planned).
|
||||
- Haiku
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue