reactivity.esm-bundler.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. import { EMPTY_OBJ, isArray, isMap, isIntegerKey, isSymbol, extend, hasOwn, isObject, hasChanged, capitalize, toRawType, def, isFunction, NOOP } from '@vue/shared';
  2. const targetMap = new WeakMap();
  3. const effectStack = [];
  4. let activeEffect;
  5. const ITERATE_KEY = Symbol((process.env.NODE_ENV !== 'production') ? 'iterate' : '');
  6. const MAP_KEY_ITERATE_KEY = Symbol((process.env.NODE_ENV !== 'production') ? 'Map key iterate' : '');
  7. function isEffect(fn) {
  8. return fn && fn._isEffect === true;
  9. }
  10. function effect(fn, options = EMPTY_OBJ) {
  11. if (isEffect(fn)) {
  12. fn = fn.raw;
  13. }
  14. const effect = createReactiveEffect(fn, options);
  15. if (!options.lazy) {
  16. effect();
  17. }
  18. return effect;
  19. }
  20. function stop(effect) {
  21. if (effect.active) {
  22. cleanup(effect);
  23. if (effect.options.onStop) {
  24. effect.options.onStop();
  25. }
  26. effect.active = false;
  27. }
  28. }
  29. let uid = 0;
  30. function createReactiveEffect(fn, options) {
  31. const effect = function reactiveEffect() {
  32. if (!effect.active) {
  33. return options.scheduler ? undefined : fn();
  34. }
  35. if (!effectStack.includes(effect)) {
  36. cleanup(effect);
  37. try {
  38. enableTracking();
  39. effectStack.push(effect);
  40. activeEffect = effect;
  41. return fn();
  42. }
  43. finally {
  44. effectStack.pop();
  45. resetTracking();
  46. activeEffect = effectStack[effectStack.length - 1];
  47. }
  48. }
  49. };
  50. effect.id = uid++;
  51. effect.allowRecurse = !!options.allowRecurse;
  52. effect._isEffect = true;
  53. effect.active = true;
  54. effect.raw = fn;
  55. effect.deps = [];
  56. effect.options = options;
  57. return effect;
  58. }
  59. function cleanup(effect) {
  60. const { deps } = effect;
  61. if (deps.length) {
  62. for (let i = 0; i < deps.length; i++) {
  63. deps[i].delete(effect);
  64. }
  65. deps.length = 0;
  66. }
  67. }
  68. let shouldTrack = true;
  69. const trackStack = [];
  70. function pauseTracking() {
  71. trackStack.push(shouldTrack);
  72. shouldTrack = false;
  73. }
  74. function enableTracking() {
  75. trackStack.push(shouldTrack);
  76. shouldTrack = true;
  77. }
  78. function resetTracking() {
  79. const last = trackStack.pop();
  80. shouldTrack = last === undefined ? true : last;
  81. }
  82. function track(target, type, key) {
  83. if (!shouldTrack || activeEffect === undefined) {
  84. return;
  85. }
  86. let depsMap = targetMap.get(target);
  87. if (!depsMap) {
  88. targetMap.set(target, (depsMap = new Map()));
  89. }
  90. let dep = depsMap.get(key);
  91. if (!dep) {
  92. depsMap.set(key, (dep = new Set()));
  93. }
  94. if (!dep.has(activeEffect)) {
  95. dep.add(activeEffect);
  96. activeEffect.deps.push(dep);
  97. if ((process.env.NODE_ENV !== 'production') && activeEffect.options.onTrack) {
  98. activeEffect.options.onTrack({
  99. effect: activeEffect,
  100. target,
  101. type,
  102. key
  103. });
  104. }
  105. }
  106. }
  107. function trigger(target, type, key, newValue, oldValue, oldTarget) {
  108. const depsMap = targetMap.get(target);
  109. if (!depsMap) {
  110. // never been tracked
  111. return;
  112. }
  113. const effects = new Set();
  114. const add = (effectsToAdd) => {
  115. if (effectsToAdd) {
  116. effectsToAdd.forEach(effect => {
  117. if (effect !== activeEffect || effect.allowRecurse) {
  118. effects.add(effect);
  119. }
  120. });
  121. }
  122. };
  123. if (type === "clear" /* CLEAR */) {
  124. // collection being cleared
  125. // trigger all effects for target
  126. depsMap.forEach(add);
  127. }
  128. else if (key === 'length' && isArray(target)) {
  129. depsMap.forEach((dep, key) => {
  130. if (key === 'length' || key >= newValue) {
  131. add(dep);
  132. }
  133. });
  134. }
  135. else {
  136. // schedule runs for SET | ADD | DELETE
  137. if (key !== void 0) {
  138. add(depsMap.get(key));
  139. }
  140. // also run for iteration key on ADD | DELETE | Map.SET
  141. switch (type) {
  142. case "add" /* ADD */:
  143. if (!isArray(target)) {
  144. add(depsMap.get(ITERATE_KEY));
  145. if (isMap(target)) {
  146. add(depsMap.get(MAP_KEY_ITERATE_KEY));
  147. }
  148. }
  149. else if (isIntegerKey(key)) {
  150. // new index added to array -> length changes
  151. add(depsMap.get('length'));
  152. }
  153. break;
  154. case "delete" /* DELETE */:
  155. if (!isArray(target)) {
  156. add(depsMap.get(ITERATE_KEY));
  157. if (isMap(target)) {
  158. add(depsMap.get(MAP_KEY_ITERATE_KEY));
  159. }
  160. }
  161. break;
  162. case "set" /* SET */:
  163. if (isMap(target)) {
  164. add(depsMap.get(ITERATE_KEY));
  165. }
  166. break;
  167. }
  168. }
  169. const run = (effect) => {
  170. if ((process.env.NODE_ENV !== 'production') && effect.options.onTrigger) {
  171. effect.options.onTrigger({
  172. effect,
  173. target,
  174. key,
  175. type,
  176. newValue,
  177. oldValue,
  178. oldTarget
  179. });
  180. }
  181. if (effect.options.scheduler) {
  182. effect.options.scheduler(effect);
  183. }
  184. else {
  185. effect();
  186. }
  187. };
  188. effects.forEach(run);
  189. }
  190. const builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol)
  191. .map(key => Symbol[key])
  192. .filter(isSymbol));
  193. const get = /*#__PURE__*/ createGetter();
  194. const shallowGet = /*#__PURE__*/ createGetter(false, true);
  195. const readonlyGet = /*#__PURE__*/ createGetter(true);
  196. const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true);
  197. const arrayInstrumentations = {};
  198. ['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
  199. const method = Array.prototype[key];
  200. arrayInstrumentations[key] = function (...args) {
  201. const arr = toRaw(this);
  202. for (let i = 0, l = this.length; i < l; i++) {
  203. track(arr, "get" /* GET */, i + '');
  204. }
  205. // we run the method using the original args first (which may be reactive)
  206. const res = method.apply(arr, args);
  207. if (res === -1 || res === false) {
  208. // if that didn't work, run it again using raw values.
  209. return method.apply(arr, args.map(toRaw));
  210. }
  211. else {
  212. return res;
  213. }
  214. };
  215. });
  216. ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {
  217. const method = Array.prototype[key];
  218. arrayInstrumentations[key] = function (...args) {
  219. pauseTracking();
  220. const res = method.apply(this, args);
  221. resetTracking();
  222. return res;
  223. };
  224. });
  225. function createGetter(isReadonly = false, shallow = false) {
  226. return function get(target, key, receiver) {
  227. if (key === "__v_isReactive" /* IS_REACTIVE */) {
  228. return !isReadonly;
  229. }
  230. else if (key === "__v_isReadonly" /* IS_READONLY */) {
  231. return isReadonly;
  232. }
  233. else if (key === "__v_raw" /* RAW */ &&
  234. receiver === (isReadonly ? readonlyMap : reactiveMap).get(target)) {
  235. return target;
  236. }
  237. const targetIsArray = isArray(target);
  238. if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
  239. return Reflect.get(arrayInstrumentations, key, receiver);
  240. }
  241. const res = Reflect.get(target, key, receiver);
  242. if (isSymbol(key)
  243. ? builtInSymbols.has(key)
  244. : key === `__proto__` || key === `__v_isRef`) {
  245. return res;
  246. }
  247. if (!isReadonly) {
  248. track(target, "get" /* GET */, key);
  249. }
  250. if (shallow) {
  251. return res;
  252. }
  253. if (isRef(res)) {
  254. // ref unwrapping - does not apply for Array + integer key.
  255. const shouldUnwrap = !targetIsArray || !isIntegerKey(key);
  256. return shouldUnwrap ? res.value : res;
  257. }
  258. if (isObject(res)) {
  259. // Convert returned value into a proxy as well. we do the isObject check
  260. // here to avoid invalid value warning. Also need to lazy access readonly
  261. // and reactive here to avoid circular dependency.
  262. return isReadonly ? readonly(res) : reactive(res);
  263. }
  264. return res;
  265. };
  266. }
  267. const set = /*#__PURE__*/ createSetter();
  268. const shallowSet = /*#__PURE__*/ createSetter(true);
  269. function createSetter(shallow = false) {
  270. return function set(target, key, value, receiver) {
  271. const oldValue = target[key];
  272. if (!shallow) {
  273. value = toRaw(value);
  274. if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
  275. oldValue.value = value;
  276. return true;
  277. }
  278. }
  279. const hadKey = isArray(target) && isIntegerKey(key)
  280. ? Number(key) < target.length
  281. : hasOwn(target, key);
  282. const result = Reflect.set(target, key, value, receiver);
  283. // don't trigger if target is something up in the prototype chain of original
  284. if (target === toRaw(receiver)) {
  285. if (!hadKey) {
  286. trigger(target, "add" /* ADD */, key, value);
  287. }
  288. else if (hasChanged(value, oldValue)) {
  289. trigger(target, "set" /* SET */, key, value, oldValue);
  290. }
  291. }
  292. return result;
  293. };
  294. }
  295. function deleteProperty(target, key) {
  296. const hadKey = hasOwn(target, key);
  297. const oldValue = target[key];
  298. const result = Reflect.deleteProperty(target, key);
  299. if (result && hadKey) {
  300. trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
  301. }
  302. return result;
  303. }
  304. function has(target, key) {
  305. const result = Reflect.has(target, key);
  306. if (!isSymbol(key) || !builtInSymbols.has(key)) {
  307. track(target, "has" /* HAS */, key);
  308. }
  309. return result;
  310. }
  311. function ownKeys(target) {
  312. track(target, "iterate" /* ITERATE */, isArray(target) ? 'length' : ITERATE_KEY);
  313. return Reflect.ownKeys(target);
  314. }
  315. const mutableHandlers = {
  316. get,
  317. set,
  318. deleteProperty,
  319. has,
  320. ownKeys
  321. };
  322. const readonlyHandlers = {
  323. get: readonlyGet,
  324. set(target, key) {
  325. if ((process.env.NODE_ENV !== 'production')) {
  326. console.warn(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
  327. }
  328. return true;
  329. },
  330. deleteProperty(target, key) {
  331. if ((process.env.NODE_ENV !== 'production')) {
  332. console.warn(`Delete operation on key "${String(key)}" failed: target is readonly.`, target);
  333. }
  334. return true;
  335. }
  336. };
  337. const shallowReactiveHandlers = extend({}, mutableHandlers, {
  338. get: shallowGet,
  339. set: shallowSet
  340. });
  341. // Props handlers are special in the sense that it should not unwrap top-level
  342. // refs (in order to allow refs to be explicitly passed down), but should
  343. // retain the reactivity of the normal readonly object.
  344. const shallowReadonlyHandlers = extend({}, readonlyHandlers, {
  345. get: shallowReadonlyGet
  346. });
  347. const toReactive = (value) => isObject(value) ? reactive(value) : value;
  348. const toReadonly = (value) => isObject(value) ? readonly(value) : value;
  349. const toShallow = (value) => value;
  350. const getProto = (v) => Reflect.getPrototypeOf(v);
  351. function get$1(target, key, isReadonly = false, isShallow = false) {
  352. // #1772: readonly(reactive(Map)) should return readonly + reactive version
  353. // of the value
  354. target = target["__v_raw" /* RAW */];
  355. const rawTarget = toRaw(target);
  356. const rawKey = toRaw(key);
  357. if (key !== rawKey) {
  358. !isReadonly && track(rawTarget, "get" /* GET */, key);
  359. }
  360. !isReadonly && track(rawTarget, "get" /* GET */, rawKey);
  361. const { has } = getProto(rawTarget);
  362. const wrap = isReadonly ? toReadonly : isShallow ? toShallow : toReactive;
  363. if (has.call(rawTarget, key)) {
  364. return wrap(target.get(key));
  365. }
  366. else if (has.call(rawTarget, rawKey)) {
  367. return wrap(target.get(rawKey));
  368. }
  369. }
  370. function has$1(key, isReadonly = false) {
  371. const target = this["__v_raw" /* RAW */];
  372. const rawTarget = toRaw(target);
  373. const rawKey = toRaw(key);
  374. if (key !== rawKey) {
  375. !isReadonly && track(rawTarget, "has" /* HAS */, key);
  376. }
  377. !isReadonly && track(rawTarget, "has" /* HAS */, rawKey);
  378. return key === rawKey
  379. ? target.has(key)
  380. : target.has(key) || target.has(rawKey);
  381. }
  382. function size(target, isReadonly = false) {
  383. target = target["__v_raw" /* RAW */];
  384. !isReadonly && track(toRaw(target), "iterate" /* ITERATE */, ITERATE_KEY);
  385. return Reflect.get(target, 'size', target);
  386. }
  387. function add(value) {
  388. value = toRaw(value);
  389. const target = toRaw(this);
  390. const proto = getProto(target);
  391. const hadKey = proto.has.call(target, value);
  392. const result = target.add(value);
  393. if (!hadKey) {
  394. trigger(target, "add" /* ADD */, value, value);
  395. }
  396. return result;
  397. }
  398. function set$1(key, value) {
  399. value = toRaw(value);
  400. const target = toRaw(this);
  401. const { has, get } = getProto(target);
  402. let hadKey = has.call(target, key);
  403. if (!hadKey) {
  404. key = toRaw(key);
  405. hadKey = has.call(target, key);
  406. }
  407. else if ((process.env.NODE_ENV !== 'production')) {
  408. checkIdentityKeys(target, has, key);
  409. }
  410. const oldValue = get.call(target, key);
  411. const result = target.set(key, value);
  412. if (!hadKey) {
  413. trigger(target, "add" /* ADD */, key, value);
  414. }
  415. else if (hasChanged(value, oldValue)) {
  416. trigger(target, "set" /* SET */, key, value, oldValue);
  417. }
  418. return result;
  419. }
  420. function deleteEntry(key) {
  421. const target = toRaw(this);
  422. const { has, get } = getProto(target);
  423. let hadKey = has.call(target, key);
  424. if (!hadKey) {
  425. key = toRaw(key);
  426. hadKey = has.call(target, key);
  427. }
  428. else if ((process.env.NODE_ENV !== 'production')) {
  429. checkIdentityKeys(target, has, key);
  430. }
  431. const oldValue = get ? get.call(target, key) : undefined;
  432. // forward the operation before queueing reactions
  433. const result = target.delete(key);
  434. if (hadKey) {
  435. trigger(target, "delete" /* DELETE */, key, undefined, oldValue);
  436. }
  437. return result;
  438. }
  439. function clear() {
  440. const target = toRaw(this);
  441. const hadItems = target.size !== 0;
  442. const oldTarget = (process.env.NODE_ENV !== 'production')
  443. ? isMap(target)
  444. ? new Map(target)
  445. : new Set(target)
  446. : undefined;
  447. // forward the operation before queueing reactions
  448. const result = target.clear();
  449. if (hadItems) {
  450. trigger(target, "clear" /* CLEAR */, undefined, undefined, oldTarget);
  451. }
  452. return result;
  453. }
  454. function createForEach(isReadonly, isShallow) {
  455. return function forEach(callback, thisArg) {
  456. const observed = this;
  457. const target = observed["__v_raw" /* RAW */];
  458. const rawTarget = toRaw(target);
  459. const wrap = isReadonly ? toReadonly : isShallow ? toShallow : toReactive;
  460. !isReadonly && track(rawTarget, "iterate" /* ITERATE */, ITERATE_KEY);
  461. return target.forEach((value, key) => {
  462. // important: make sure the callback is
  463. // 1. invoked with the reactive map as `this` and 3rd arg
  464. // 2. the value received should be a corresponding reactive/readonly.
  465. return callback.call(thisArg, wrap(value), wrap(key), observed);
  466. });
  467. };
  468. }
  469. function createIterableMethod(method, isReadonly, isShallow) {
  470. return function (...args) {
  471. const target = this["__v_raw" /* RAW */];
  472. const rawTarget = toRaw(target);
  473. const targetIsMap = isMap(rawTarget);
  474. const isPair = method === 'entries' || (method === Symbol.iterator && targetIsMap);
  475. const isKeyOnly = method === 'keys' && targetIsMap;
  476. const innerIterator = target[method](...args);
  477. const wrap = isReadonly ? toReadonly : isShallow ? toShallow : toReactive;
  478. !isReadonly &&
  479. track(rawTarget, "iterate" /* ITERATE */, isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY);
  480. // return a wrapped iterator which returns observed versions of the
  481. // values emitted from the real iterator
  482. return {
  483. // iterator protocol
  484. next() {
  485. const { value, done } = innerIterator.next();
  486. return done
  487. ? { value, done }
  488. : {
  489. value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
  490. done
  491. };
  492. },
  493. // iterable protocol
  494. [Symbol.iterator]() {
  495. return this;
  496. }
  497. };
  498. };
  499. }
  500. function createReadonlyMethod(type) {
  501. return function (...args) {
  502. if ((process.env.NODE_ENV !== 'production')) {
  503. const key = args[0] ? `on key "${args[0]}" ` : ``;
  504. console.warn(`${capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this));
  505. }
  506. return type === "delete" /* DELETE */ ? false : this;
  507. };
  508. }
  509. const mutableInstrumentations = {
  510. get(key) {
  511. return get$1(this, key);
  512. },
  513. get size() {
  514. return size(this);
  515. },
  516. has: has$1,
  517. add,
  518. set: set$1,
  519. delete: deleteEntry,
  520. clear,
  521. forEach: createForEach(false, false)
  522. };
  523. const shallowInstrumentations = {
  524. get(key) {
  525. return get$1(this, key, false, true);
  526. },
  527. get size() {
  528. return size(this);
  529. },
  530. has: has$1,
  531. add,
  532. set: set$1,
  533. delete: deleteEntry,
  534. clear,
  535. forEach: createForEach(false, true)
  536. };
  537. const readonlyInstrumentations = {
  538. get(key) {
  539. return get$1(this, key, true);
  540. },
  541. get size() {
  542. return size(this, true);
  543. },
  544. has(key) {
  545. return has$1.call(this, key, true);
  546. },
  547. add: createReadonlyMethod("add" /* ADD */),
  548. set: createReadonlyMethod("set" /* SET */),
  549. delete: createReadonlyMethod("delete" /* DELETE */),
  550. clear: createReadonlyMethod("clear" /* CLEAR */),
  551. forEach: createForEach(true, false)
  552. };
  553. const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator];
  554. iteratorMethods.forEach(method => {
  555. mutableInstrumentations[method] = createIterableMethod(method, false, false);
  556. readonlyInstrumentations[method] = createIterableMethod(method, true, false);
  557. shallowInstrumentations[method] = createIterableMethod(method, false, true);
  558. });
  559. function createInstrumentationGetter(isReadonly, shallow) {
  560. const instrumentations = shallow
  561. ? shallowInstrumentations
  562. : isReadonly
  563. ? readonlyInstrumentations
  564. : mutableInstrumentations;
  565. return (target, key, receiver) => {
  566. if (key === "__v_isReactive" /* IS_REACTIVE */) {
  567. return !isReadonly;
  568. }
  569. else if (key === "__v_isReadonly" /* IS_READONLY */) {
  570. return isReadonly;
  571. }
  572. else if (key === "__v_raw" /* RAW */) {
  573. return target;
  574. }
  575. return Reflect.get(hasOwn(instrumentations, key) && key in target
  576. ? instrumentations
  577. : target, key, receiver);
  578. };
  579. }
  580. const mutableCollectionHandlers = {
  581. get: createInstrumentationGetter(false, false)
  582. };
  583. const shallowCollectionHandlers = {
  584. get: createInstrumentationGetter(false, true)
  585. };
  586. const readonlyCollectionHandlers = {
  587. get: createInstrumentationGetter(true, false)
  588. };
  589. function checkIdentityKeys(target, has, key) {
  590. const rawKey = toRaw(key);
  591. if (rawKey !== key && has.call(target, rawKey)) {
  592. const type = toRawType(target);
  593. console.warn(`Reactive ${type} contains both the raw and reactive ` +
  594. `versions of the same object${type === `Map` ? ` as keys` : ``}, ` +
  595. `which can lead to inconsistencies. ` +
  596. `Avoid differentiating between the raw and reactive versions ` +
  597. `of an object and only use the reactive version if possible.`);
  598. }
  599. }
  600. const reactiveMap = new WeakMap();
  601. const readonlyMap = new WeakMap();
  602. function targetTypeMap(rawType) {
  603. switch (rawType) {
  604. case 'Object':
  605. case 'Array':
  606. return 1 /* COMMON */;
  607. case 'Map':
  608. case 'Set':
  609. case 'WeakMap':
  610. case 'WeakSet':
  611. return 2 /* COLLECTION */;
  612. default:
  613. return 0 /* INVALID */;
  614. }
  615. }
  616. function getTargetType(value) {
  617. return value["__v_skip" /* SKIP */] || !Object.isExtensible(value)
  618. ? 0 /* INVALID */
  619. : targetTypeMap(toRawType(value));
  620. }
  621. function reactive(target) {
  622. // if trying to observe a readonly proxy, return the readonly version.
  623. if (target && target["__v_isReadonly" /* IS_READONLY */]) {
  624. return target;
  625. }
  626. return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers);
  627. }
  628. // Return a reactive-copy of the original object, where only the root level
  629. // properties are reactive, and does NOT unwrap refs nor recursively convert
  630. // returned properties.
  631. function shallowReactive(target) {
  632. return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers);
  633. }
  634. function readonly(target) {
  635. return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers);
  636. }
  637. // Return a reactive-copy of the original object, where only the root level
  638. // properties are readonly, and does NOT unwrap refs nor recursively convert
  639. // returned properties.
  640. // This is used for creating the props proxy object for stateful components.
  641. function shallowReadonly(target) {
  642. return createReactiveObject(target, true, shallowReadonlyHandlers, readonlyCollectionHandlers);
  643. }
  644. function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers) {
  645. if (!isObject(target)) {
  646. if ((process.env.NODE_ENV !== 'production')) {
  647. console.warn(`value cannot be made reactive: ${String(target)}`);
  648. }
  649. return target;
  650. }
  651. // target is already a Proxy, return it.
  652. // exception: calling readonly() on a reactive object
  653. if (target["__v_raw" /* RAW */] &&
  654. !(isReadonly && target["__v_isReactive" /* IS_REACTIVE */])) {
  655. return target;
  656. }
  657. // target already has corresponding Proxy
  658. const proxyMap = isReadonly ? readonlyMap : reactiveMap;
  659. const existingProxy = proxyMap.get(target);
  660. if (existingProxy) {
  661. return existingProxy;
  662. }
  663. // only a whitelist of value types can be observed.
  664. const targetType = getTargetType(target);
  665. if (targetType === 0 /* INVALID */) {
  666. return target;
  667. }
  668. const proxy = new Proxy(target, targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers);
  669. proxyMap.set(target, proxy);
  670. return proxy;
  671. }
  672. function isReactive(value) {
  673. if (isReadonly(value)) {
  674. return isReactive(value["__v_raw" /* RAW */]);
  675. }
  676. return !!(value && value["__v_isReactive" /* IS_REACTIVE */]);
  677. }
  678. function isReadonly(value) {
  679. return !!(value && value["__v_isReadonly" /* IS_READONLY */]);
  680. }
  681. function isProxy(value) {
  682. return isReactive(value) || isReadonly(value);
  683. }
  684. function toRaw(observed) {
  685. return ((observed && toRaw(observed["__v_raw" /* RAW */])) || observed);
  686. }
  687. function markRaw(value) {
  688. def(value, "__v_skip" /* SKIP */, true);
  689. return value;
  690. }
  691. const convert = (val) => isObject(val) ? reactive(val) : val;
  692. function isRef(r) {
  693. return Boolean(r && r.__v_isRef === true);
  694. }
  695. function ref(value) {
  696. return createRef(value);
  697. }
  698. function shallowRef(value) {
  699. return createRef(value, true);
  700. }
  701. class RefImpl {
  702. constructor(_rawValue, _shallow = false) {
  703. this._rawValue = _rawValue;
  704. this._shallow = _shallow;
  705. this.__v_isRef = true;
  706. this._value = _shallow ? _rawValue : convert(_rawValue);
  707. }
  708. get value() {
  709. track(toRaw(this), "get" /* GET */, 'value');
  710. return this._value;
  711. }
  712. set value(newVal) {
  713. if (hasChanged(toRaw(newVal), this._rawValue)) {
  714. this._rawValue = newVal;
  715. this._value = this._shallow ? newVal : convert(newVal);
  716. trigger(toRaw(this), "set" /* SET */, 'value', newVal);
  717. }
  718. }
  719. }
  720. function createRef(rawValue, shallow = false) {
  721. if (isRef(rawValue)) {
  722. return rawValue;
  723. }
  724. return new RefImpl(rawValue, shallow);
  725. }
  726. function triggerRef(ref) {
  727. trigger(toRaw(ref), "set" /* SET */, 'value', (process.env.NODE_ENV !== 'production') ? ref.value : void 0);
  728. }
  729. function unref(ref) {
  730. return isRef(ref) ? ref.value : ref;
  731. }
  732. const shallowUnwrapHandlers = {
  733. get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
  734. set: (target, key, value, receiver) => {
  735. const oldValue = target[key];
  736. if (isRef(oldValue) && !isRef(value)) {
  737. oldValue.value = value;
  738. return true;
  739. }
  740. else {
  741. return Reflect.set(target, key, value, receiver);
  742. }
  743. }
  744. };
  745. function proxyRefs(objectWithRefs) {
  746. return isReactive(objectWithRefs)
  747. ? objectWithRefs
  748. : new Proxy(objectWithRefs, shallowUnwrapHandlers);
  749. }
  750. class CustomRefImpl {
  751. constructor(factory) {
  752. this.__v_isRef = true;
  753. const { get, set } = factory(() => track(this, "get" /* GET */, 'value'), () => trigger(this, "set" /* SET */, 'value'));
  754. this._get = get;
  755. this._set = set;
  756. }
  757. get value() {
  758. return this._get();
  759. }
  760. set value(newVal) {
  761. this._set(newVal);
  762. }
  763. }
  764. function customRef(factory) {
  765. return new CustomRefImpl(factory);
  766. }
  767. function toRefs(object) {
  768. if ((process.env.NODE_ENV !== 'production') && !isProxy(object)) {
  769. console.warn(`toRefs() expects a reactive object but received a plain one.`);
  770. }
  771. const ret = isArray(object) ? new Array(object.length) : {};
  772. for (const key in object) {
  773. ret[key] = toRef(object, key);
  774. }
  775. return ret;
  776. }
  777. class ObjectRefImpl {
  778. constructor(_object, _key) {
  779. this._object = _object;
  780. this._key = _key;
  781. this.__v_isRef = true;
  782. }
  783. get value() {
  784. return this._object[this._key];
  785. }
  786. set value(newVal) {
  787. this._object[this._key] = newVal;
  788. }
  789. }
  790. function toRef(object, key) {
  791. return isRef(object[key])
  792. ? object[key]
  793. : new ObjectRefImpl(object, key);
  794. }
  795. class ComputedRefImpl {
  796. constructor(getter, _setter, isReadonly) {
  797. this._setter = _setter;
  798. this._dirty = true;
  799. this.__v_isRef = true;
  800. this.effect = effect(getter, {
  801. lazy: true,
  802. scheduler: () => {
  803. if (!this._dirty) {
  804. this._dirty = true;
  805. trigger(toRaw(this), "set" /* SET */, 'value');
  806. }
  807. }
  808. });
  809. this["__v_isReadonly" /* IS_READONLY */] = isReadonly;
  810. }
  811. get value() {
  812. if (this._dirty) {
  813. this._value = this.effect();
  814. this._dirty = false;
  815. }
  816. track(toRaw(this), "get" /* GET */, 'value');
  817. return this._value;
  818. }
  819. set value(newValue) {
  820. this._setter(newValue);
  821. }
  822. }
  823. function computed(getterOrOptions) {
  824. let getter;
  825. let setter;
  826. if (isFunction(getterOrOptions)) {
  827. getter = getterOrOptions;
  828. setter = (process.env.NODE_ENV !== 'production')
  829. ? () => {
  830. console.warn('Write operation failed: computed value is readonly');
  831. }
  832. : NOOP;
  833. }
  834. else {
  835. getter = getterOrOptions.get;
  836. setter = getterOrOptions.set;
  837. }
  838. return new ComputedRefImpl(getter, setter, isFunction(getterOrOptions) || !getterOrOptions.set);
  839. }
  840. export { ITERATE_KEY, computed, customRef, effect, enableTracking, isProxy, isReactive, isReadonly, isRef, markRaw, pauseTracking, proxyRefs, reactive, readonly, ref, resetTracking, shallowReactive, shallowReadonly, shallowRef, stop, toRaw, toRef, toRefs, track, trigger, triggerRef, unref };