Coverage Report

Created: 2025-06-24 07:03

/src/moddable/xs/sources/xsmc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016-2021  Moddable Tech, Inc.
3
 *
4
 *   This file is part of the Moddable SDK Runtime.
5
 * 
6
 *   The Moddable SDK Runtime is free software: you can redistribute it and/or modify
7
 *   it under the terms of the GNU Lesser General Public License as published by
8
 *   the Free Software Foundation, either version 3 of the License, or
9
 *   (at your option) any later version.
10
 * 
11
 *   The Moddable SDK Runtime is distributed in the hope that it will be useful,
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *   GNU Lesser General Public License for more details.
15
 * 
16
 *   You should have received a copy of the GNU Lesser General Public License
17
 *   along with the Moddable SDK Runtime.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * This file incorporates work covered by the following copyright and  
20
 * permission notice:  
21
 *
22
 *       Copyright (C) 2010-2016 Marvell International Ltd.
23
 *       Copyright (C) 2002-2010 Kinoma, Inc.
24
 *
25
 *       Licensed under the Apache License, Version 2.0 (the "License");
26
 *       you may not use this file except in compliance with the License.
27
 *       You may obtain a copy of the License at
28
 *
29
 *        http://www.apache.org/licenses/LICENSE-2.0
30
 *
31
 *       Unless required by applicable law or agreed to in writing, software
32
 *       distributed under the License is distributed on an "AS IS" BASIS,
33
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
 *       See the License for the specific language governing permissions and
35
 *       limitations under the License.
36
 */
37
38
#include "xsAll.h"
39
#include <stdio.h>
40
41
#ifndef ICACHE_XS6STRING_ATTR
42
  #define ICACHE_XS6STRING_ATTR
43
#endif
44
45
27.8k
#define fxPop() (*(the->stack++))
46
306k
#define fxPush(_SLOT) (*(--the->stack) = (_SLOT))
47
48
void _xsNewArray(txMachine *the, txSlot *res, txInteger length)
49
0
{
50
0
  fxNewArray(the, length);
51
0
  *res = fxPop();
52
0
}
53
54
void _xsNewObject(txMachine *the, txSlot *res)
55
0
{
56
0
  fxNewObject(the);
57
0
  *res = fxPop();
58
0
}
59
60
void _xsNewHostInstance(txMachine *the, txSlot *res, txSlot *proto)
61
0
{
62
0
  mxOverflow(-1);
63
0
  fxPush(*proto);
64
0
  fxNewHostInstance(the);
65
0
  *res = fxPop();
66
0
}
67
68
txBoolean _xsIsInstanceOf(txMachine *the, txSlot *v, txSlot *proto)
69
0
{
70
0
  mxOverflow(-2);
71
0
  fxPush(*proto);
72
0
  fxPush(*v);
73
0
  return fxIsInstanceOf(the);
74
0
}
75
76
txBoolean _xsHas(txMachine *the, txSlot *self, txID id)
77
0
{
78
0
  mxOverflow(-1);
79
0
  fxPush(*self);
80
0
  return mxHasID(id);
81
0
}
82
83
txBoolean _xsHasIndex(txMachine *the, txSlot *self, txIndex index)
84
0
{
85
0
  mxOverflow(-1);
86
0
  fxPush(*self);
87
0
  return fxHasIndex(the, index);
88
0
}
89
90
void _xsGet(txMachine *the, txSlot *res, txSlot *self, txID id)
91
27.8k
{
92
27.8k
  mxOverflow(-1);
93
27.8k
  fxPush(*self);
94
27.8k
  mxGetID(id);
95
27.8k
  *res = fxPop();
96
27.8k
}
97
98
void _xsGetAt(txMachine *the, txSlot *res, txSlot *self, txSlot *at)
99
0
{
100
0
  mxOverflow(-2);
101
0
  fxPush(*self);
102
0
  fxPush(*at);
103
0
  fxGetAt(the);
104
0
  *res = fxPop();
105
0
}
106
107
void _xsGetIndex(txMachine *the, txSlot *res, txSlot *self, txIndex index)
108
0
{
109
0
  mxOverflow(-1);
110
0
  fxPush(*self);
111
0
  mxGetIndex(index);
112
0
  *res = fxPop();
113
0
}
114
115
void _xsSet(txMachine *the, txSlot *self, txID id, txSlot *v)
116
0
{
117
0
  mxOverflow(-2);
118
0
  fxPush(*v);
119
0
  fxPush(*self);
120
0
  mxSetID(id);
121
0
  mxPop();
122
0
}
123
124
void _xsSetAt(txMachine *the, txSlot *self, txSlot *at , txSlot *v)
125
0
{
126
0
  mxOverflow(-3);
127
0
  fxPush(*v);
128
0
  fxPush(*self);
129
0
  fxPush(*at);
130
0
  fxSetAt(the);
131
0
  mxPop();
132
0
}
133
134
void _xsSetIndex(txMachine *the, txSlot *self, txIndex index, txSlot *v)
135
0
{
136
0
  mxOverflow(-2);
137
0
  fxPush(*v);
138
0
  fxPush(*self);
139
0
  mxSetIndex(index);
140
0
  mxPop();
141
0
}
142
143
void _xsDefine(txMachine *the, txSlot *self, txID id, txSlot *v, txFlag attributes)
144
139k
{
145
139k
  mxOverflow(-2);
146
139k
  fxPush(*v);
147
139k
  fxPush(*self);
148
139k
  fxDefineID(the, id, attributes, attributes | XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
149
139k
  mxPop();
150
139k
}
151
152
void _xsDelete(txMachine *the, txSlot *self, txID id)
153
0
{
154
0
  mxOverflow(-1);
155
0
  fxPush(*self);
156
0
  mxDeleteID(id);
157
0
}
158
159
void _xsDeleteAt(txMachine *the, txSlot *self, txSlot *at)
160
0
{
161
0
  mxOverflow(-2);
162
0
  fxPush(*self);
163
0
  fxPush(*at);
164
0
  fxDeleteAt(the);
165
0
}
166
167
void _xsCall(txMachine *the, txSlot *res, txSlot *self, txUnsigned id, ...)
168
0
{
169
0
  va_list ap;
170
0
  int n;
171
0
  txSlot *v;
172
173
0
  va_start(ap, id);
174
0
  for (n = 0; va_arg(ap, txSlot *) != NULL; n++)
175
0
    ;
176
0
  va_end(ap);
177
0
  mxOverflow(-(n+6));
178
0
  fxPush(*self);
179
0
  fxCallID(the, (txID)id);
180
0
  va_start(ap, id);
181
0
  while ((v = va_arg(ap, txSlot *)) != NULL)
182
0
    fxPush(*v);
183
0
  va_end(ap);
184
0
  fxRunCount(the, n);
185
0
  if (res != NULL)
186
0
    *res = fxPop();
187
0
  else
188
0
    mxPop();
189
0
}
190
191
void _xsNew(txMachine *the, txSlot *res, txSlot *self, txUnsigned id, ...)
192
0
{
193
0
  va_list ap;
194
0
  int n;
195
0
  txSlot *v;
196
197
0
  va_start(ap, id);
198
0
  for (n = 0; va_arg(ap, txSlot *) != NULL; n++)
199
0
    ;
200
0
  va_end(ap);
201
0
  mxOverflow(-(n+6));
202
0
  fxPush(*self);
203
0
  fxNewID(the, (txID)id);
204
0
  va_start(ap, id);
205
0
  while ((v = va_arg(ap, txSlot *)) != NULL)
206
0
    fxPush(*v);
207
0
  va_end(ap);
208
0
  fxRunCount(the, n);
209
0
  *res = fxPop();
210
0
}
211
212
txBoolean _xsTest(txMachine *the, txSlot *v)
213
0
{
214
0
  mxOverflow(-1);
215
0
  fxPush(*v);
216
0
  return fxRunTest(the);
217
0
}
218
219
txInteger fxIncrementalVars(txMachine* the, txInteger theCount)
220
27.8k
{
221
27.8k
  txSlot* aStack = the->scope;
222
27.8k
  txInteger aVar;
223
224
27.8k
  if (aStack - aStack->value.integer != the->stack) {
225
0
    static const char msg[] ICACHE_XS6STRING_ATTR = "C: xsVars: too late";
226
0
    mxSyntaxError((char *)msg);
227
0
  }
228
27.8k
  mxOverflow(theCount);
229
27.8k
  aVar = aStack->value.integer;
230
27.8k
  aStack->value.integer += theCount;
231
27.8k
  if (theCount > 0) {
232
111k
    while (theCount) {
233
83.5k
      mxPushUndefined();
234
83.5k
      theCount--;
235
83.5k
    }
236
27.8k
  }
237
0
  else
238
0
    the->stack -= theCount;
239
27.8k
  return aVar;
240
27.8k
}
241
242
txInteger _xsArgc(txMachine *the)
243
55.7k
{
244
55.7k
  return mxArgc;
245
55.7k
}
246
247
#ifndef __XSMC_H__
248
enum {
249
  xsBufferNonrelocatable,
250
  xsBufferRelocatable
251
};
252
#endif
253
254
static txInteger _xsmcGetViewBuffer(txMachine *the, txSlot* view, txSlot* buffer, void **data, txUnsigned *count, txBoolean writable)
255
0
{
256
0
  txInteger offset = view->value.dataView.offset;
257
0
  txInteger size = view->value.dataView.size;
258
0
  txSlot* arrayBuffer = buffer->value.reference->next;
259
0
  txSlot* bufferInfo = arrayBuffer->next;
260
0
  if (arrayBuffer->value.arrayBuffer.address == C_NULL)
261
0
    mxTypeError("detached buffer");
262
0
  if (writable && (arrayBuffer->flag & XS_DONT_SET_FLAG))
263
0
    mxTypeError("read-only buffer");
264
0
  if (bufferInfo->value.bufferInfo.maxLength >= 0) {
265
0
    txInteger byteLength = bufferInfo->value.bufferInfo.length;
266
0
    if (offset > byteLength)
267
0
      mxTypeError("out of bounds view");
268
0
    if (size < 0)
269
0
      size = byteLength - offset;
270
0
    else if (offset + size > byteLength)
271
0
      mxTypeError("out of bounds view");
272
0
  }
273
0
  *data = arrayBuffer->value.arrayBuffer.address + offset;
274
0
  *count = size;
275
276
0
  return (XS_ARRAY_BUFFER_KIND == arrayBuffer->kind) ? xsBufferRelocatable : xsBufferNonrelocatable;
277
0
}
278
279
txInteger _xsmcGetBuffer(txMachine *the, txSlot *slot, void **data, txUnsigned *count, txBoolean writable)
280
55.7k
{
281
55.7k
  txSlot* instance;
282
283
55.7k
  if (slot->kind != XS_REFERENCE_KIND)
284
0
    goto bail;
285
286
55.7k
  instance = slot->value.reference;
287
55.7k
  if (!(((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG)))
288
0
    goto bail;
289
290
55.7k
  if (slot->kind == XS_ARRAY_BUFFER_KIND) {
291
55.7k
    txSlot* bufferInfo = slot->next;
292
55.7k
    if (slot->value.arrayBuffer.address == C_NULL)
293
0
      mxTypeError("detached buffer");
294
55.7k
    if (writable && (slot->flag & XS_DONT_SET_FLAG))
295
0
      mxTypeError("read-only buffer");
296
55.7k
    *data = slot->value.arrayBuffer.address;
297
55.7k
    *count = bufferInfo->value.bufferInfo.length;
298
55.7k
    return xsBufferRelocatable;
299
55.7k
  }
300
301
0
  if (slot->kind == XS_TYPED_ARRAY_KIND) {
302
0
    txSlot* view = slot->next;
303
0
    txSlot* buffer = view->next;
304
0
    if (1 != slot->value.typedArray.dispatch->size)
305
0
      goto bail;
306
0
    return _xsmcGetViewBuffer(the, view, buffer, data, count, writable);
307
0
  }
308
  
309
0
  if (slot->kind == XS_HOST_KIND) {
310
0
    txSlot* bufferInfo = slot->next;
311
0
    if (slot->flag & XS_HOST_CHUNK_FLAG)
312
0
      goto bail;
313
0
    if (writable && (slot->flag & XS_DONT_SET_FLAG))
314
0
      mxTypeError("read-only buffer");
315
0
    if (bufferInfo && (bufferInfo->kind == XS_BUFFER_INFO_KIND)) {
316
0
      *data = (uint8_t *)slot->value.host.data;
317
0
      *count = bufferInfo->value.bufferInfo.length;
318
0
    }
319
0
    else {
320
      // for compatibility. should throw eventually.
321
0
      txSlot tmp, ref;
322
0
      fxReport(the, "# Use xsmcSetHostBuffer instead of xsmcSetHostData\n");
323
0
      fxReference(the, &ref, instance);
324
0
      _xsGet(the, &tmp, &ref, _byteLength);
325
0
      *data = (uint8_t *)slot->value.host.data;
326
0
      *count = (txUnsigned)fxToInteger(the, &tmp);
327
0
    }
328
0
    return xsBufferNonrelocatable;
329
0
  }
330
331
0
  if (slot->kind == XS_DATA_VIEW_KIND) {
332
0
    txSlot* view = slot;
333
0
    txSlot* buffer = view->next;
334
0
    return _xsmcGetViewBuffer(the, view, buffer, data, count, writable);
335
0
  }
336
337
0
bail:
338
0
  mxTypeError("invalid buffer");
339
0
  return xsBufferNonrelocatable;
340
0
}