Compare commits

..

No commits in common. "main" and "13.2-release" have entirely different histories.

493 changed files with 611 additions and 211980 deletions

View file

@ -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@");

View file

@ -1 +1 @@
52.13.2.1
52.13.2

View file

@ -1 +1 @@
13.2.1
13.2

View file

@ -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

View file

@ -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.

View file

@ -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);

View file

@ -1929,9 +1929,6 @@ public:
{
ProcessGlobal* global = ProcessGlobal::Get();
MOZ_ASSERT(!aRunInGlobalScope);
if (NS_WARN_IF(!global)) {
return false;
}
global->LoadScript(aURL);
return true;
}

View file

@ -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);

View file

@ -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")));

View file

@ -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)

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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. */

View file

@ -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

View file

@ -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; }

View file

@ -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() {

View file

@ -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);

View file

@ -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

View file

@ -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++;
}

View file

@ -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

View file

@ -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 */

View file

@ -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);

View file

@ -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_;

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}

View file

@ -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 */

View file

@ -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.

View file

@ -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 {

View file

@ -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) {

View file

@ -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);
}

View file

@ -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,

View file

@ -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_);

View file

@ -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

View file

@ -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

View file

@ -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)
{

View file

@ -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);

View file

@ -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")

View file

@ -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);
}

View file

@ -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&)

View file

@ -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;
}

View file

@ -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)); \
}

View file

@ -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)

View file

@ -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). */

View file

@ -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

View file

@ -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',

View file

@ -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);

View file

@ -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>

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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 {

View file

@ -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);
}

View file

@ -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") \

View file

@ -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);
}

View file

@ -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());

View file

@ -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;
}
/*

View file

@ -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),

View file

@ -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
};

View file

@ -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();
}

View file

@ -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"

View file

@ -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:

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -127,7 +127,6 @@ UNIFIED_SOURCES += [
'CounterStyleManager.cpp',
'CSS.cpp',
'CSSLexer.cpp',
'CSSNestingFlattener.cpp',
'CSSRuleList.cpp',
'CSSStyleSheet.cpp',
'CSSVariableDeclarations.cpp',

View file

@ -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,

View file

@ -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]

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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);

View file

@ -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']

View file

@ -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.

View file

@ -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

View file

@ -1,3 +0,0 @@
Completion:
HeaderInsertion: Never
ClangFormat: Tab

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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()

View file

@ -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

View file

@ -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()
}
}
}
}
}

View file

@ -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.

View file

@ -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$@ $<

View file

@ -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)

View file

@ -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

View file

@ -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);

View file

@ -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)`).

View file

@ -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

View file

@ -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