Skip to content

ModelSchemaProvider._loadModelSchema causes infinite recursion via ShimModelClass #10498

@paddor

Description

@paddor

Bug

ModelSchemaProvider._loadModelSchema(type) in @warp-drive/legacy@5.8.1 causes RangeError: Maximum call stack size exceeded.

Stack trace

handlers.js:11 Uncaught (in promise) RangeError: Maximum call stack size exceeded
    at invoke (handlers.js:11:27)
    at deprecate (deprecate.js:187:5)
    at Store.modelFor (index-CQP2NSqg.js:5823:26)
    at ModelSchemaProvider._loadModelSchema (schema-provider-DJCV_6AF.js:2127:35)
    at ModelSchemaProvider.fields (schema-provider-DJCV_6AF.js:2160:12)
    at DelegatingSchemaService.fields (migration-support.js:470:28)
    at get attributes (index-CQP2NSqg.js:5546:40)
    at ModelSchemaProvider._loadModelSchema (schema-provider-DJCV_6AF.js:2128:37)
    at ModelSchemaProvider.fields (schema-provider-DJCV_6AF.js:2160:12)

Root cause

In @warp-drive/legacy schema-provider, _loadModelSchema(type) calls this.store.modelFor(type). In @warp-drive/core 5.8.1, Store.prototype.modelFor returns a ShimModelClass (not the actual Model class). The ShimModelClass.get attributes() getter calls this.__store.schema.fields({type}), which goes through DelegatingSchemaService.fields()ModelSchemaProvider.fields(). Since the schema isn't cached yet (we're still inside _loadModelSchema), fields() calls _loadModelSchema(type) again — infinite recursion.

The cycle:

  1. _loadModelSchema(type) — line 2150: const modelClass = this.store.modelFor(type) → returns ShimModelClass
  2. Line 2151: modelClass.attributes → triggers ShimModelClass.get attributes()
  3. get attributes() calls store.schema.fields({type}) (core index line 5567)
  4. DelegatingSchemaService.fields()ModelSchemaProvider.fields() → checks cache → miss → calls _loadModelSchema(type) → goto 1

Fix

Replace this.store.modelFor(type) with getModelFactory(this.store, type).class in _loadModelSchema. The getModelFactory function is already defined in the same file and returns the actual Model class from the Ember container — whose static attributes property doesn't call back into the schema system.

  _loadModelSchema(type) {
-   const modelClass = this.store.modelFor(type);
+   const factory = getModelFactory(this.store, type);
+   const modelClass = factory.class;
    const attributeMap = modelClass.attributes;

Versions

  • @warp-drive/core: 5.8.1
  • @warp-drive/legacy: 5.8.1
  • ember-source: 6.8.0
  • Using DelegatingSchemaService from @warp-drive/legacy/model/migration-support

Reproduction

Any app using DelegatingSchemaService with @warp-drive/legacy models that triggers store.schema.fields() or ModelSchemaProvider.fields() will hit this. It happens on the first access to any model's schema.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions